-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from FuriousPws002/07-dynamic-sql
07 dynamic sql
- Loading branch information
Showing
14 changed files
with
501 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
src/main/java/org/apache/ibatis/scripting/xmltags/DynamicSqlSource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package org.apache.ibatis.scripting.xmltags; | ||
|
||
import org.apache.ibatis.builder.SqlSourceBuilder; | ||
import org.apache.ibatis.mapping.BoundSql; | ||
import org.apache.ibatis.mapping.SqlSource; | ||
import org.apache.ibatis.session.Configuration; | ||
|
||
/** | ||
* @author furious 2024/4/16 | ||
*/ | ||
public class DynamicSqlSource implements SqlSource { | ||
|
||
private final Configuration configuration; | ||
private final SqlNode rootSqlNode; | ||
|
||
public DynamicSqlSource(Configuration configuration, SqlNode rootSqlNode) { | ||
this.configuration = configuration; | ||
this.rootSqlNode = rootSqlNode; | ||
} | ||
|
||
@Override | ||
public BoundSql getBoundSql(Object parameterObject) { | ||
DynamicContext context = new DynamicContext(parameterObject); | ||
rootSqlNode.apply(context); | ||
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration); | ||
Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass(); | ||
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType); | ||
BoundSql boundSql = sqlSource.getBoundSql(parameterObject); | ||
context.getBindings().forEach(boundSql::setAdditionalParameter); | ||
return boundSql; | ||
} | ||
} |
157 changes: 157 additions & 0 deletions
157
src/main/java/org/apache/ibatis/scripting/xmltags/ForeachSqlNode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
package org.apache.ibatis.scripting.xmltags; | ||
|
||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
import org.apache.commons.lang3.StringUtils; | ||
import org.apache.ibatis.parsing.GenericTokenParser; | ||
|
||
import ognl.Ognl; | ||
|
||
/** | ||
* @author furious 2024/4/17 | ||
*/ | ||
public class ForeachSqlNode implements SqlNode { | ||
|
||
public static final String ITEM_PREFIX = ForeachSqlNode.class.getName(); | ||
|
||
private final SqlNode contents; | ||
private final String collection; | ||
private final String item; | ||
private final String open; | ||
private final String close; | ||
private final String separator; | ||
|
||
public ForeachSqlNode(SqlNode contents, String collection, String item, String open, String close, String separator) { | ||
this.contents = contents; | ||
this.collection = collection; | ||
this.item = item; | ||
this.open = open; | ||
this.close = close; | ||
this.separator = separator; | ||
} | ||
|
||
@Override | ||
@SuppressWarnings("rawtypes") | ||
public boolean apply(DynamicContext context) { | ||
Iterable<?> iterable = null; | ||
try { | ||
Object value = Ognl.getValue(Ognl.parseExpression(collection), context.getParameterObject()); | ||
if (value instanceof Iterable && ((Iterable) value).iterator().hasNext()) { | ||
iterable = (Iterable) value; | ||
} | ||
} catch (Exception e) { | ||
return false; | ||
} | ||
if (Objects.isNull(iterable)) { | ||
return true; | ||
} | ||
|
||
applyOpen(context); | ||
int index = 0; | ||
for (Object o : iterable) { | ||
DynamicContext oldContext = context; | ||
if (index == 0) { | ||
context = new SeparatorContext(context, ""); | ||
} else { | ||
context = new SeparatorContext(context, separator); | ||
} | ||
applyItem(context, o, index); | ||
contents.apply(new FilteredDynamicContext(context, item, index)); | ||
context = oldContext; | ||
index++; | ||
} | ||
applyClose(context); | ||
return true; | ||
} | ||
|
||
private void applyOpen(DynamicContext context) { | ||
if (Objects.nonNull(open)) { | ||
context.appendSql(open); | ||
} | ||
} | ||
|
||
private void applyItem(DynamicContext context, Object o, int i) { | ||
if (Objects.nonNull(item)) { | ||
context.bind(item, o); | ||
context.bind(itemizeItem(item, i), o); | ||
} | ||
} | ||
|
||
private void applyClose(DynamicContext context) { | ||
if (Objects.nonNull(close)) { | ||
context.appendSql(close); | ||
} | ||
} | ||
|
||
private static String itemizeItem(String item, int i) { | ||
return ITEM_PREFIX + item + "_" + i; | ||
} | ||
|
||
private static class SeparatorContext extends DynamicContext { | ||
|
||
private final DynamicContext delegate; | ||
private final String separator; | ||
|
||
public SeparatorContext(DynamicContext delegate, String separator) { | ||
this.delegate = delegate; | ||
this.separator = separator; | ||
} | ||
|
||
@Override | ||
public Map<String, Object> getBindings() { | ||
return delegate.getBindings(); | ||
} | ||
|
||
@Override | ||
public void bind(String name, Object value) { | ||
delegate.bind(name, value); | ||
} | ||
|
||
@Override | ||
public void appendSql(String sql) { | ||
if (StringUtils.isNoneBlank(sql)) { | ||
delegate.appendSql(separator); | ||
} | ||
delegate.appendSql(sql); | ||
} | ||
|
||
@Override | ||
public String getSql() { | ||
return delegate.getSql(); | ||
} | ||
} | ||
|
||
private static class FilteredDynamicContext extends DynamicContext { | ||
private final DynamicContext delegate; | ||
private final String item; | ||
private final int index; | ||
|
||
public FilteredDynamicContext(DynamicContext delegate, String item, int index) { | ||
this.delegate = delegate; | ||
this.item = item; | ||
this.index = index; | ||
} | ||
|
||
@Override | ||
public Map<String, Object> getBindings() { | ||
return delegate.getBindings(); | ||
} | ||
|
||
@Override | ||
public void bind(String name, Object value) { | ||
delegate.bind(name, value); | ||
} | ||
|
||
@Override | ||
public String getSql() { | ||
return delegate.getSql(); | ||
} | ||
|
||
@Override | ||
public void appendSql(String sql) { | ||
GenericTokenParser parser = new GenericTokenParser("#{", "}", content -> "#{" + itemizeItem(item, index) + "}"); | ||
delegate.appendSql(parser.parse(sql)); | ||
} | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
src/main/java/org/apache/ibatis/scripting/xmltags/IfSqlNode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package org.apache.ibatis.scripting.xmltags; | ||
|
||
import ognl.Ognl; | ||
|
||
/** | ||
* @author furious 2024/4/16 | ||
*/ | ||
public class IfSqlNode implements SqlNode { | ||
|
||
private final String test; | ||
private final SqlNode contents; | ||
|
||
public IfSqlNode(String test, SqlNode contents) { | ||
this.test = test; | ||
this.contents = contents; | ||
} | ||
|
||
@Override | ||
public boolean apply(DynamicContext context) { | ||
try { | ||
Object value = Ognl.getValue(Ognl.parseExpression(test), context.getParameterObject()); | ||
if (value instanceof Boolean && (Boolean) value) { | ||
contents.apply(context); | ||
} | ||
return true; | ||
} catch (Exception e) { | ||
return false; | ||
} | ||
} | ||
} |
Oops, something went wrong.