INT-3210: JDBC & JPA: Optimize SpEL Parsing
JIRA: https://jira.springsource.org/browse/INT-3210 * Parse `Expression` parameters only once at creation phase * There is still tiny case, when configured parameters don't have provided parameter, in this case an `input` determines as JavaBean and the `name` will be populated as bean property via SpEL. INT-3210: Add params to maps and collections * If configured parameters don't contain provide param, parse his expressions and add to parameters of current `ParameterSource` and enclosing `ParameterSourceFactory` * Move JPA `ExpressionEvaluatingParameterSource` to inner class of `ExpressionEvaluatingParameterSourceFactory`, similar to `ExpressionEvaluatingSqlParameterSourceFactory`
This commit is contained in:
committed by
Gary Russell
parent
5bb6e550aa
commit
6b50c49efe
@@ -21,7 +21,10 @@ import java.util.Map;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionException;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.util.AbstractExpressionEvaluator;
|
||||
import org.springframework.jdbc.core.namedparam.AbstractSqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
||||
@@ -33,6 +36,7 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
||||
* @author Dave Syer
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ExpressionEvaluatingSqlParameterSourceFactory extends AbstractExpressionEvaluator implements
|
||||
@@ -40,15 +44,23 @@ public class ExpressionEvaluatingSqlParameterSourceFactory extends AbstractExpre
|
||||
|
||||
private final static Log logger = LogFactory.getLog(ExpressionEvaluatingSqlParameterSourceFactory.class);
|
||||
|
||||
private static final ExpressionParser PARSER = new SpelExpressionParser();
|
||||
|
||||
private static final Object ERROR = new Object();
|
||||
|
||||
private volatile Map<String, ?> staticParameters;
|
||||
|
||||
private volatile Map<String, String> parameterExpressions;
|
||||
/**
|
||||
* The {@link Map} of parameters with expressions.
|
||||
* {@code key} - parameter name; {@code value} - array of two {@link Expression}s:
|
||||
* first element - direct {@link Expression}, second - collection projection {@link Expression}.
|
||||
* Used in case of root object of evaluation is {@link Collection}.
|
||||
*/
|
||||
private volatile Map<String, Expression[]> parameterExpressions;
|
||||
|
||||
public ExpressionEvaluatingSqlParameterSourceFactory() {
|
||||
this.staticParameters = Collections.unmodifiableMap(new HashMap<String, Object>());
|
||||
this.parameterExpressions = Collections.unmodifiableMap(new HashMap<String, String>());
|
||||
this.parameterExpressions = new HashMap<String, Expression[]>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,13 +110,21 @@ public class ExpressionEvaluatingSqlParameterSourceFactory extends AbstractExpre
|
||||
* @param parameterExpressions the parameter expressions to set
|
||||
*/
|
||||
public void setParameterExpressions(Map<String, String> parameterExpressions) {
|
||||
this.parameterExpressions = parameterExpressions;
|
||||
Map<String, Expression[]> paramExpressions = new HashMap<String, Expression[]>(parameterExpressions.size());
|
||||
for (Map.Entry<String, String> entry : parameterExpressions.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String expression = entry.getValue();
|
||||
Expression[] expressions = new Expression[] {
|
||||
PARSER.parseExpression(expression),
|
||||
PARSER.parseExpression("#root.![" + expression + "]")
|
||||
};
|
||||
paramExpressions.put(key, expressions);
|
||||
}
|
||||
this.parameterExpressions = paramExpressions;
|
||||
}
|
||||
|
||||
public SqlParameterSource createParameterSource(final Object input) {
|
||||
SqlParameterSource toReturn = new ExpressionEvaluatingSqlParameterSource(input, staticParameters,
|
||||
parameterExpressions);
|
||||
return toReturn;
|
||||
return new ExpressionEvaluatingSqlParameterSource(input, this.staticParameters, this.parameterExpressions);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -119,10 +139,10 @@ public class ExpressionEvaluatingSqlParameterSourceFactory extends AbstractExpre
|
||||
|
||||
private volatile Map<String, Object> values = new HashMap<String, Object>();
|
||||
|
||||
private final Map<String, String> parameterExpressions;
|
||||
private final Map<String, Expression[]> parameterExpressions;
|
||||
|
||||
private ExpressionEvaluatingSqlParameterSource(Object input, Map<String, ?> staticParameters,
|
||||
Map<String, String> parameterExpressions) {
|
||||
Map<String, Expression[]> parameterExpressions) {
|
||||
this.input = input;
|
||||
this.parameterExpressions = parameterExpressions;
|
||||
this.values.putAll(staticParameters);
|
||||
@@ -132,13 +152,25 @@ public class ExpressionEvaluatingSqlParameterSourceFactory extends AbstractExpre
|
||||
if (values.containsKey(paramName)) {
|
||||
return values.get(paramName);
|
||||
}
|
||||
String expression = paramName;
|
||||
if (parameterExpressions.containsKey(expression)) {
|
||||
expression = parameterExpressions.get(expression);
|
||||
|
||||
if (!parameterExpressions.containsKey(paramName)) {
|
||||
Expression[] expressions = new Expression[] {
|
||||
PARSER.parseExpression(paramName),
|
||||
PARSER.parseExpression("#root.![" + paramName + "]")
|
||||
};
|
||||
ExpressionEvaluatingSqlParameterSourceFactory.this.parameterExpressions.put(paramName, expressions);
|
||||
this.parameterExpressions.put(paramName, expressions);
|
||||
}
|
||||
|
||||
Expression expression = null;
|
||||
|
||||
if (input instanceof Collection<?>) {
|
||||
expression = "#root.![" + expression + "]";
|
||||
expression = parameterExpressions.get(paramName)[1];
|
||||
}
|
||||
else {
|
||||
expression = parameterExpressions.get(paramName)[0];
|
||||
}
|
||||
|
||||
Object value = evaluateExpression(expression, input);
|
||||
values.put(paramName, value);
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
Reference in New Issue
Block a user