forked from p81075629/datagear
[persistence,web]persistence模块添加变量表达式支持,为批量添加操作时的类似“#{index*3+1}”(index为批量索引)的表达式提供支持
This commit is contained in:
parent
96eb17dd34
commit
c3cd0885ad
|
@ -28,6 +28,11 @@
|
|||
<artifactId>datagear-dbinfo</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
|
|
|
@ -0,0 +1,341 @@
|
|||
/*
|
||||
* Copyright (c) 2018 datagear.org. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package org.datagear.persistence.support;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.datagear.connection.JdbcUtil;
|
||||
import org.datagear.model.Model;
|
||||
import org.datagear.model.Property;
|
||||
import org.datagear.model.support.MU;
|
||||
import org.datagear.persistence.UnsupportedModelCharacterException;
|
||||
import org.datagear.persistence.support.ExpressionResolver.Expression;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
|
||||
/**
|
||||
* 抽象支持表达式的持久化操作类。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractExpressionModelPersistenceOperation extends AbstractModelPersistenceOperation
|
||||
{
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ExpressionResolver variableExpressionResolver;
|
||||
|
||||
private ExpressionResolver sqlExpressionResolver;
|
||||
|
||||
private SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
|
||||
|
||||
public AbstractExpressionModelPersistenceOperation()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public AbstractExpressionModelPersistenceOperation(ConversionService conversionService,
|
||||
ExpressionResolver variableExpressionResolver, ExpressionResolver sqlExpressionResolver)
|
||||
{
|
||||
super();
|
||||
this.conversionService = conversionService;
|
||||
this.variableExpressionResolver = variableExpressionResolver;
|
||||
this.sqlExpressionResolver = sqlExpressionResolver;
|
||||
}
|
||||
|
||||
public ConversionService getConversionService()
|
||||
{
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
public void setConversionService(ConversionService conversionService)
|
||||
{
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public ExpressionResolver getVariableExpressionResolver()
|
||||
{
|
||||
return variableExpressionResolver;
|
||||
}
|
||||
|
||||
public void setVariableExpressionResolver(ExpressionResolver variableExpressionResolver)
|
||||
{
|
||||
this.variableExpressionResolver = variableExpressionResolver;
|
||||
}
|
||||
|
||||
public ExpressionResolver getSqlExpressionResolver()
|
||||
{
|
||||
return sqlExpressionResolver;
|
||||
}
|
||||
|
||||
public void setSqlExpressionResolver(ExpressionResolver sqlExpressionResolver)
|
||||
{
|
||||
this.sqlExpressionResolver = sqlExpressionResolver;
|
||||
}
|
||||
|
||||
public SpelExpressionParser getSpelExpressionParser()
|
||||
{
|
||||
return spelExpressionParser;
|
||||
}
|
||||
|
||||
public void setSpelExpressionParser(SpelExpressionParser spelExpressionParser)
|
||||
{
|
||||
this.spelExpressionParser = spelExpressionParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析表达式属性值。
|
||||
* <p>
|
||||
* 如果包含表达式,返回计算结果;否则,直接返回{@code propValue}。
|
||||
* </p>
|
||||
*
|
||||
* @param cn
|
||||
* @param model
|
||||
* @param property
|
||||
* @param expressionPropValue
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
protected Object evaluatePropertyValueIfExpression(Connection cn, Model model, Property property, Object propValue,
|
||||
ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
List<Expression> variableExpressions = this.variableExpressionResolver.resolve(propValue);
|
||||
|
||||
Object evaluatedPropValue = propValue;
|
||||
|
||||
if (variableExpressions != null && !variableExpressions.isEmpty())
|
||||
{
|
||||
String strPropValue = (String) propValue;
|
||||
|
||||
checkValidExpressionProperty(model, property, strPropValue);
|
||||
|
||||
evaluatedPropValue = evaluateVariableExpressions(strPropValue, variableExpressions,
|
||||
expressionEvaluationContext);
|
||||
}
|
||||
|
||||
List<Expression> sqlExpressions = this.sqlExpressionResolver.resolve(evaluatedPropValue);
|
||||
|
||||
if (sqlExpressions != null && !sqlExpressions.isEmpty())
|
||||
{
|
||||
String strPropValue = (String) evaluatedPropValue;
|
||||
|
||||
checkValidExpressionProperty(model, property, strPropValue);
|
||||
|
||||
evaluatedPropValue = evaluateSqlExpressions(cn, strPropValue, sqlExpressions, expressionEvaluationContext);
|
||||
}
|
||||
|
||||
if (evaluatedPropValue != propValue)
|
||||
{
|
||||
Class<?> propertyType = property.getModel().getType();
|
||||
propValue = this.conversionService.convert(evaluatedPropValue, propertyType);
|
||||
}
|
||||
|
||||
return propValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算给定变量表达式的值。
|
||||
*
|
||||
* @param source
|
||||
* 变量表达式字符串
|
||||
* @param expressions
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
* @throws VariableExpressionErrorException
|
||||
*/
|
||||
protected Object evaluateVariableExpressions(String source, List<Expression> expressions,
|
||||
ExpressionEvaluationContext expressionEvaluationContext) throws VariableExpressionErrorException
|
||||
{
|
||||
List<Object> expressionValues = new ArrayList<Object>();
|
||||
|
||||
for (int i = 0, len = expressions.size(); i < len; i++)
|
||||
{
|
||||
Expression expression = expressions.get(i);
|
||||
|
||||
if (expressionEvaluationContext.containsCachedValue(expression))
|
||||
{
|
||||
Object value = expressionEvaluationContext.getCachedValue(expression);
|
||||
expressionValues.add(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
evaluateAsVariableExpression(expression, expressionEvaluationContext, expressionValues);
|
||||
}
|
||||
}
|
||||
|
||||
String evaluated = this.variableExpressionResolver.evaluate(source, expressions, expressionValues, "");
|
||||
|
||||
return evaluated;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算给定SQL表达式的值。
|
||||
* <p>
|
||||
* 如果表达式并不符合{@linkplain #isSelectSql(String)},那么此方法则会将它作为变量表达式求值,这使得在不需要变量表达式内嵌SQL表达式的情况下,可以仅使用SQL表达式的语法,简化使用难度。
|
||||
* </p>
|
||||
*
|
||||
* @param cn
|
||||
* @param source
|
||||
* SQL表达式字符串
|
||||
* @param expressions
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
* @throws SqlExpressionErrorException
|
||||
* @throws VariableExpressionErrorException
|
||||
*/
|
||||
protected Object evaluateSqlExpressions(Connection cn, String source, List<Expression> expressions,
|
||||
ExpressionEvaluationContext expressionEvaluationContext)
|
||||
throws SqlExpressionErrorException, VariableExpressionErrorException
|
||||
{
|
||||
List<Object> expressionValues = new ArrayList<Object>();
|
||||
|
||||
for (int i = 0, len = expressions.size(); i < len; i++)
|
||||
{
|
||||
Expression expression = expressions.get(i);
|
||||
|
||||
if (expressionEvaluationContext.containsCachedValue(expression))
|
||||
{
|
||||
Object value = expressionEvaluationContext.getCachedValue(expression);
|
||||
expressionValues.add(value);
|
||||
}
|
||||
else if (isSelectSql(expression.getContent()))
|
||||
{
|
||||
evaluateAsSelectSqlExpression(expression, expressionEvaluationContext, expressionValues, cn);
|
||||
}
|
||||
else
|
||||
{
|
||||
evaluateAsVariableExpression(expression, expressionEvaluationContext, expressionValues);
|
||||
}
|
||||
}
|
||||
|
||||
String evaluated = this.sqlExpressionResolver.evaluate(source, expressions, expressionValues, "");
|
||||
|
||||
return evaluated;
|
||||
}
|
||||
|
||||
/**
|
||||
* 作为SQL表达式求值。
|
||||
*
|
||||
* @param expression
|
||||
* @param expressionEvaluationContext
|
||||
* @param expressionValues
|
||||
* @param cn
|
||||
* @throws SqlExpressionErrorException
|
||||
*/
|
||||
protected void evaluateAsSelectSqlExpression(Expression expression,
|
||||
ExpressionEvaluationContext expressionEvaluationContext, List<Object> expressionValues, Connection cn)
|
||||
throws SqlExpressionErrorException
|
||||
{
|
||||
Statement st = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{
|
||||
st = cn.createStatement();
|
||||
rs = st.executeQuery(expression.getContent());
|
||||
|
||||
Object value = null;
|
||||
|
||||
if (rs.next())
|
||||
value = rs.getObject(1);
|
||||
|
||||
expressionValues.add(value);
|
||||
expressionEvaluationContext.putCachedValue(expression, value);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new SqlExpressionErrorException(expression, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
JdbcUtil.closeResultSet(rs);
|
||||
JdbcUtil.closeStatement(st);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 作为变量表达式求值。
|
||||
*
|
||||
* @param expression
|
||||
* @param expressionEvaluationContext
|
||||
* @param expressionValues
|
||||
* @throws VariableExpressionErrorException
|
||||
*/
|
||||
protected void evaluateAsVariableExpression(Expression expression,
|
||||
ExpressionEvaluationContext expressionEvaluationContext, List<Object> expressionValues)
|
||||
throws VariableExpressionErrorException
|
||||
{
|
||||
try
|
||||
{
|
||||
Object value = this.spelExpressionParser.parseExpression(expression.getContent())
|
||||
.getValue(expressionEvaluationContext.getVariableExpressionBean());
|
||||
|
||||
expressionValues.add(value);
|
||||
expressionEvaluationContext.putCachedValue(expression, value);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new VariableExpressionErrorException(expression, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查属性是否可使用表达式。
|
||||
*
|
||||
* @param model
|
||||
* @param property
|
||||
* @param expressionPropValue
|
||||
*/
|
||||
protected void checkValidExpressionProperty(Model model, Property property, String expressionPropValue)
|
||||
{
|
||||
if (!isValidExpressionProperty(model, property))
|
||||
throw new UnsupportedModelCharacterException("[" + model + "] 's [" + property + "] is expression ["
|
||||
+ expressionPropValue + "], it must be single, concrete and primitive.");
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断属性是否可使用表达式值。
|
||||
*
|
||||
* @param model
|
||||
* @param property
|
||||
* @return
|
||||
*/
|
||||
protected boolean isValidExpressionProperty(Model model, Property property)
|
||||
{
|
||||
return (MU.isSingleProperty(property) && MU.isConcretePrimitiveProperty(property));
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断给定对象是否是表达式。
|
||||
*
|
||||
* @param obj
|
||||
* @return
|
||||
*/
|
||||
protected boolean isExpression(Object obj)
|
||||
{
|
||||
return this.variableExpressionResolver.isExpression(obj) || this.sqlExpressionResolver.isExpression(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断给定SQL语句是否是“SELECT”语句。
|
||||
*
|
||||
* @param sql
|
||||
* @return
|
||||
*/
|
||||
protected boolean isSelectSql(String sql)
|
||||
{
|
||||
if (sql == null || sql.isEmpty())
|
||||
return false;
|
||||
|
||||
return Pattern.matches(SELECT_SQL_REGEX, sql);
|
||||
}
|
||||
|
||||
protected static final String SELECT_SQL_REGEX = "^\\s*((?i)select)\\s+\\S+[\\s\\S]*$";
|
||||
}
|
|
@ -4,23 +4,6 @@
|
|||
|
||||
package org.datagear.persistence.support;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.datagear.connection.JdbcUtil;
|
||||
import org.datagear.model.Model;
|
||||
import org.datagear.model.Property;
|
||||
import org.datagear.model.support.MU;
|
||||
import org.datagear.persistence.UnsupportedModelCharacterException;
|
||||
import org.datagear.persistence.support.ExpressionResolver.Expression;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
|
||||
/**
|
||||
* 抽象持久化操作类。
|
||||
* <p>
|
||||
|
@ -42,91 +25,4 @@ public abstract class AbstractModelPersistenceOperation extends AbstractModelDat
|
|||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算给定表达式的真正属性值。
|
||||
*
|
||||
* @param cn
|
||||
* @param model
|
||||
* @param property
|
||||
* @param expressionPropValue
|
||||
* @param expressions
|
||||
* @param expressionValueCache
|
||||
* @param conversionService
|
||||
* @param expressionResolver
|
||||
* @return
|
||||
*/
|
||||
protected Object evaluatePropertyValueForQueryExpressions(Connection cn, Model model, Property property,
|
||||
String expressionPropValue, List<Expression> expressions, Map<String, Object> expressionValueCache,
|
||||
ConversionService conversionService, ExpressionResolver expressionResolver)
|
||||
{
|
||||
if (!MU.isSingleProperty(property) || !MU.isConcretePrimitiveProperty(property))
|
||||
throw new UnsupportedModelCharacterException("[" + model + "] 's [" + property + "] is sql expression ["
|
||||
+ expressionPropValue + "], it must be single, concrete and primitive.");
|
||||
|
||||
List<Object> expressionValues = new ArrayList<Object>();
|
||||
|
||||
for (int i = 0, len = expressions.size(); i < len; i++)
|
||||
{
|
||||
Expression expression = expressions.get(i);
|
||||
|
||||
String cacheKey = (expression.hasName() ? expression.getName() : expression.getContent());
|
||||
|
||||
if (expressionValueCache.containsKey(cacheKey))
|
||||
{
|
||||
Object value = expressionValueCache.get(cacheKey);
|
||||
expressionValues.add(value);
|
||||
}
|
||||
else if (!isSelectSql(expression.getContent()))
|
||||
{
|
||||
expressionValues.add(expression.getExpression());
|
||||
}
|
||||
else
|
||||
{
|
||||
Statement st = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{
|
||||
st = cn.createStatement();
|
||||
rs = st.executeQuery(expression.getContent());
|
||||
|
||||
Object value = null;
|
||||
|
||||
if (rs.next())
|
||||
value = rs.getObject(1);
|
||||
|
||||
expressionValues.add(value);
|
||||
expressionValueCache.put(cacheKey, value);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new SqlExpressionErrorException(expression, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
JdbcUtil.closeResultSet(rs);
|
||||
JdbcUtil.closeStatement(st);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String evaluated = expressionResolver.evaluate(expressionPropValue, expressions, expressionValues, "");
|
||||
|
||||
return conversionService.convert(evaluated, property.getModel().getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断给定SQL语句是否是“SELECT”语句。
|
||||
*
|
||||
* @param sql
|
||||
* @return
|
||||
*/
|
||||
protected boolean isSelectSql(String sql)
|
||||
{
|
||||
if (sql == null || sql.isEmpty())
|
||||
return false;
|
||||
|
||||
return Pattern.matches(SELECT_SQL_REGEX, sql);
|
||||
}
|
||||
|
||||
protected static final String SELECT_SQL_REGEX = "^\\s*((?i)select)\\s+\\S+[\\s\\S]*$";
|
||||
}
|
||||
|
|
|
@ -38,7 +38,9 @@ public class DefaultPersistenceManager extends AbstractModelDataAccessObject imp
|
|||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ExpressionResolver expressionResolver;
|
||||
private ExpressionResolver variableExpressionResolver;
|
||||
|
||||
private ExpressionResolver sqlExpressionResolver;
|
||||
|
||||
private InsertPersistenceOperation insertPersistenceOperation;
|
||||
|
||||
|
@ -59,12 +61,20 @@ public class DefaultPersistenceManager extends AbstractModelDataAccessObject imp
|
|||
|
||||
this.dialectSource = dialectSource;
|
||||
this.conversionService = conversionService;
|
||||
this.expressionResolver = new ExpressionResolver();
|
||||
|
||||
this.variableExpressionResolver = new VariableExpressionResolver();
|
||||
|
||||
this.sqlExpressionResolver = new SqlExpressionResolver();
|
||||
|
||||
this.insertPersistenceOperation = new InsertPersistenceOperation(this.conversionService,
|
||||
this.expressionResolver);
|
||||
this.variableExpressionResolver, this.sqlExpressionResolver);
|
||||
|
||||
this.deletePersistenceOperation = new DeletePersistenceOperation();
|
||||
|
||||
this.updatePersistenceOperation = new UpdatePersistenceOperation(this.insertPersistenceOperation,
|
||||
this.deletePersistenceOperation, this.conversionService, this.expressionResolver);
|
||||
this.deletePersistenceOperation, this.conversionService, this.variableExpressionResolver,
|
||||
this.sqlExpressionResolver);
|
||||
|
||||
this.selectPersistenceOperation = new SelectPersistenceOperation();
|
||||
}
|
||||
|
||||
|
@ -90,16 +100,28 @@ public class DefaultPersistenceManager extends AbstractModelDataAccessObject imp
|
|||
this.updatePersistenceOperation.setConversionService(conversionService);
|
||||
}
|
||||
|
||||
public ExpressionResolver getExpressionResolver()
|
||||
public ExpressionResolver getVariableExpressionResolver()
|
||||
{
|
||||
return expressionResolver;
|
||||
return variableExpressionResolver;
|
||||
}
|
||||
|
||||
public void setExpressionResolver(ExpressionResolver expressionResolver)
|
||||
public void setVariableExpressionResolver(ExpressionResolver variableExpressionResolver)
|
||||
{
|
||||
this.expressionResolver = expressionResolver;
|
||||
this.insertPersistenceOperation.setExpressionResolver(expressionResolver);
|
||||
this.updatePersistenceOperation.setExpressionResolver(expressionResolver);
|
||||
this.variableExpressionResolver = variableExpressionResolver;
|
||||
this.insertPersistenceOperation.setVariableExpressionResolver(variableExpressionResolver);
|
||||
this.updatePersistenceOperation.setVariableExpressionResolver(variableExpressionResolver);
|
||||
}
|
||||
|
||||
public ExpressionResolver getSqlExpressionResolver()
|
||||
{
|
||||
return sqlExpressionResolver;
|
||||
}
|
||||
|
||||
public void setSqlExpressionResolver(ExpressionResolver sqlExpressionResolver)
|
||||
{
|
||||
this.sqlExpressionResolver = sqlExpressionResolver;
|
||||
this.insertPersistenceOperation.setSqlExpressionResolver(sqlExpressionResolver);
|
||||
this.updatePersistenceOperation.setSqlExpressionResolver(sqlExpressionResolver);
|
||||
}
|
||||
|
||||
public InsertPersistenceOperation getInsertPersistenceOperation()
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2018 datagear.org. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package org.datagear.persistence.support;
|
||||
|
||||
import org.datagear.persistence.PersistenceException;
|
||||
import org.datagear.persistence.support.ExpressionResolver.Expression;
|
||||
|
||||
/**
|
||||
* {@linkplain Expression}执行出错异常。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class ExpressionErrorException extends PersistenceException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Expression expression;
|
||||
|
||||
public ExpressionErrorException(Expression expression)
|
||||
{
|
||||
super();
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public ExpressionErrorException(Expression expression, Throwable cause)
|
||||
{
|
||||
super("Evaluate expression [" + expression.getContent() + "] error", cause);
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public Expression getExpression()
|
||||
{
|
||||
return expression;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright (c) 2018 datagear.org. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package org.datagear.persistence.support;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.datagear.persistence.support.ExpressionResolver.Expression;
|
||||
|
||||
/**
|
||||
* {@linkplain Expression}计算上下文。
|
||||
* <p>
|
||||
* 为了方便支持批量添加操作,此类的实例默认会添加{@linkplain #VARIABLE_INDEX}变量并且初值为{@code 0}。
|
||||
* </p>
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class ExpressionEvaluationContext
|
||||
{
|
||||
/** 变量名:index */
|
||||
public static final String VARIABLE_INDEX = "index";
|
||||
|
||||
/** 值缓存 */
|
||||
private Map<String, Object> valueCache = new HashMap<String, Object>();
|
||||
|
||||
/** 变量表达式求值Bean */
|
||||
private VariableExpressionBean variableExpressionBean = new VariableExpressionBean();
|
||||
|
||||
public ExpressionEvaluationContext()
|
||||
{
|
||||
super();
|
||||
this.variableExpressionBean.setIndex(0);
|
||||
}
|
||||
|
||||
public Map<String, Object> getValueCache()
|
||||
{
|
||||
return valueCache;
|
||||
}
|
||||
|
||||
public void setValueCache(Map<String, Object> valueCache)
|
||||
{
|
||||
this.valueCache = valueCache;
|
||||
}
|
||||
|
||||
public VariableExpressionBean getVariableExpressionBean()
|
||||
{
|
||||
return variableExpressionBean;
|
||||
}
|
||||
|
||||
public void setVariableExpressionBean(VariableExpressionBean variableExpressionBean)
|
||||
{
|
||||
this.variableExpressionBean = variableExpressionBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否包含指定{@linkplain Expression}的缓存值。
|
||||
*
|
||||
* @param expression
|
||||
* @return
|
||||
*/
|
||||
public boolean containsCachedValue(Expression expression)
|
||||
{
|
||||
String cacheKey = getCachedValueKey(expression);
|
||||
|
||||
return this.valueCache.containsKey(cacheKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定{@linkplain Expression}的缓存值。
|
||||
*
|
||||
* @param expression
|
||||
* @return
|
||||
*/
|
||||
public Object getCachedValue(Expression expression)
|
||||
{
|
||||
String cacheKey = getCachedValueKey(expression);
|
||||
|
||||
return this.valueCache.get(cacheKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定{@linkplain Expression}的值加入缓存。
|
||||
*
|
||||
* @param expression
|
||||
* @param value
|
||||
*/
|
||||
public void putCachedValue(Expression expression, Object value)
|
||||
{
|
||||
String cacheKey = getCachedValueKey(expression);
|
||||
|
||||
this.valueCache.put(cacheKey, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取{@linkplain #getVariableExpressionBean()}的{@linkplain VariableExpressionBean#getIndex()}的值。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getVariableIndex()
|
||||
{
|
||||
return this.variableExpressionBean.getIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置{@linkplain #getVariableExpressionBean()}的{@linkplain VariableExpressionBean#getIndex()}的值。
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
public void setVariableIndex(int value)
|
||||
{
|
||||
this.variableExpressionBean.setIndex(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将{@linkplain #getVariableExpressionBean()}的{@linkplain VariableExpressionBean#getIndex()}的值加{@code 1}并返回。
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int incrementVariableIndex()
|
||||
{
|
||||
int v = getVariableIndex() + 1;
|
||||
setVariableIndex(v);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存值关键字。
|
||||
* <p>
|
||||
* 为了使{@linkplain ExpressionResolver#DEFAULT_START_IDENTIFIER_DOLLAR}、
|
||||
* {@linkplain ExpressionResolver#DEFAULT_START_IDENTIFIER_SHARP}的表达式能使用同一个{@linkplain ExpressionEvaluationContext},
|
||||
* 此方法会生成<code>"${...}"</code>、<code>"#{...}"</code>格式的关键字。
|
||||
* </p>
|
||||
*
|
||||
* @param expression
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected String getCachedValueKey(Expression expression)
|
||||
{
|
||||
return expression.getStartIdentifier() + (expression.hasName() ? expression.getName() : expression.getContent())
|
||||
+ expression.getEndIdentifier();
|
||||
}
|
||||
}
|
|
@ -20,7 +20,11 @@ import java.util.List;
|
|||
*/
|
||||
public class ExpressionResolver
|
||||
{
|
||||
public static final String DEFAULT_START_IDENTIFIER = "${";
|
||||
/** "${"起始标识符 */
|
||||
public static final String DEFAULT_START_IDENTIFIER_DOLLAR = "${";
|
||||
|
||||
/** "#{"起始标识符 */
|
||||
public static final String DEFAULT_START_IDENTIFIER_SHARP = "#{";
|
||||
|
||||
public static final String DEFAULT_END_IDENTIFIER = "}";
|
||||
|
||||
|
@ -28,7 +32,7 @@ public class ExpressionResolver
|
|||
|
||||
public static final char DEFAULT_ESCAPER = '\\';
|
||||
|
||||
private String startIdentifier = DEFAULT_START_IDENTIFIER;
|
||||
private String startIdentifier = DEFAULT_START_IDENTIFIER_DOLLAR;
|
||||
|
||||
private String endIdentifier = DEFAULT_END_IDENTIFIER;
|
||||
|
||||
|
@ -36,7 +40,7 @@ public class ExpressionResolver
|
|||
|
||||
private char escaper = DEFAULT_ESCAPER;
|
||||
|
||||
private transient char[] _startIdentifierChars = DEFAULT_START_IDENTIFIER.toCharArray();
|
||||
private transient char[] _startIdentifierChars = DEFAULT_START_IDENTIFIER_DOLLAR.toCharArray();
|
||||
|
||||
private transient char[] _endIdentifierChars = DEFAULT_END_IDENTIFIER.toCharArray();
|
||||
|
||||
|
@ -142,9 +146,27 @@ public class ExpressionResolver
|
|||
*/
|
||||
public List<Expression> resolve(String source)
|
||||
{
|
||||
List<Expression> expressions = new ArrayList<Expression>();
|
||||
if (source == null || source.isEmpty())
|
||||
return Collections.emptyList();
|
||||
|
||||
resolve(source, expressions);
|
||||
List<Expression> expressions = null;
|
||||
|
||||
char[] cs = source.toCharArray();
|
||||
|
||||
Expression next = null;
|
||||
int startIndex = 0;
|
||||
|
||||
while ((next = resolveNextExpression(cs, startIndex)) != null)
|
||||
{
|
||||
if (expressions == null)
|
||||
expressions = new ArrayList<Expression>();
|
||||
|
||||
expressions.add(next);
|
||||
startIndex = next.getEnd();
|
||||
}
|
||||
|
||||
if (expressions == null)
|
||||
expressions = Collections.emptyList();
|
||||
|
||||
return expressions;
|
||||
}
|
||||
|
@ -192,29 +214,6 @@ public class ExpressionResolver
|
|||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析源字符串中的{@linkplain Expression},并写入给定列表。
|
||||
*
|
||||
* @param source
|
||||
* @param expressions
|
||||
*/
|
||||
protected void resolve(String source, List<Expression> expressions)
|
||||
{
|
||||
if (source == null || source.isEmpty())
|
||||
return;
|
||||
|
||||
char[] cs = source.toCharArray();
|
||||
|
||||
Expression next = null;
|
||||
int startIndex = 0;
|
||||
|
||||
while ((next = resolveNextExpression(cs, startIndex)) != null)
|
||||
{
|
||||
expressions.add(next);
|
||||
startIndex = next.getEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从给定起始位置解析下一个{@linkplain Expression}。
|
||||
* <p>
|
||||
|
@ -252,12 +251,12 @@ public class ExpressionResolver
|
|||
|
||||
if (cj == escaper)
|
||||
{
|
||||
if (cj < source.length - 1)
|
||||
if (j < source.length - 1)
|
||||
{
|
||||
if (second != null)
|
||||
second.append(cj);
|
||||
second.append(source[j + 1]);
|
||||
else
|
||||
first.append(cj);
|
||||
first.append(source[j + 1]);
|
||||
}
|
||||
|
||||
j += 1;
|
||||
|
@ -295,7 +294,8 @@ public class ExpressionResolver
|
|||
content = second.toString().trim();
|
||||
}
|
||||
|
||||
return new Expression(new String(source, i, j + 1 - i), i, j + 1, name, content);
|
||||
return new Expression(this.getStartIdentifier(), this.endIdentifier,
|
||||
new String(source, i, j + 1 - i), i, j + 1, name, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +331,7 @@ public class ExpressionResolver
|
|||
/**
|
||||
* 表达式。
|
||||
* <p>
|
||||
* 格式为:#{name:content}、#{content}
|
||||
* 格式为:${name:content}、${content}、#{name:content}、#{content}。
|
||||
* </p>
|
||||
*
|
||||
* @author datagear@163.com
|
||||
|
@ -341,6 +341,12 @@ public class ExpressionResolver
|
|||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 起始标识符 */
|
||||
private String startIdentifier;
|
||||
|
||||
/** 结束标识符 */
|
||||
private String endIdentifier;
|
||||
|
||||
/** 表达式字符串 */
|
||||
private String expression;
|
||||
|
||||
|
@ -356,18 +362,24 @@ public class ExpressionResolver
|
|||
/** 表达式内容 */
|
||||
private String content;
|
||||
|
||||
public Expression(String expression, int start, int end, String content)
|
||||
public Expression(String startIdentifier, String endIdentifier, String expression, int start, int end,
|
||||
String content)
|
||||
{
|
||||
super();
|
||||
this.startIdentifier = startIdentifier;
|
||||
this.endIdentifier = endIdentifier;
|
||||
this.expression = expression;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public Expression(String expression, int start, int end, String name, String content)
|
||||
public Expression(String startIdentifier, String endIdentifier, String expression, int start, int end,
|
||||
String name, String content)
|
||||
{
|
||||
super();
|
||||
this.startIdentifier = startIdentifier;
|
||||
this.endIdentifier = endIdentifier;
|
||||
this.expression = expression;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
|
@ -375,6 +387,26 @@ public class ExpressionResolver
|
|||
this.content = content;
|
||||
}
|
||||
|
||||
public String getStartIdentifier()
|
||||
{
|
||||
return startIdentifier;
|
||||
}
|
||||
|
||||
protected void setStartIdentifier(String startIdentifier)
|
||||
{
|
||||
this.startIdentifier = startIdentifier;
|
||||
}
|
||||
|
||||
public String getEndIdentifier()
|
||||
{
|
||||
return endIdentifier;
|
||||
}
|
||||
|
||||
protected void setEndIdentifier(String endIdentifier)
|
||||
{
|
||||
this.endIdentifier = endIdentifier;
|
||||
}
|
||||
|
||||
public String getExpression()
|
||||
{
|
||||
return expression;
|
||||
|
|
|
@ -6,9 +6,7 @@ package org.datagear.persistence.support;
|
|||
|
||||
import java.sql.Connection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.datagear.model.Model;
|
||||
import org.datagear.model.Property;
|
||||
|
@ -24,7 +22,6 @@ import org.datagear.persistence.mapper.ModelTableMapper;
|
|||
import org.datagear.persistence.mapper.PropertyModelMapper;
|
||||
import org.datagear.persistence.mapper.PropertyTableMapper;
|
||||
import org.datagear.persistence.mapper.RelationMapper;
|
||||
import org.datagear.persistence.support.ExpressionResolver.Expression;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
|
||||
/**
|
||||
|
@ -33,42 +30,17 @@ import org.springframework.core.convert.ConversionService;
|
|||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class InsertPersistenceOperation extends AbstractModelPersistenceOperation
|
||||
public class InsertPersistenceOperation extends AbstractExpressionModelPersistenceOperation
|
||||
{
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ExpressionResolver expressionResolver;
|
||||
|
||||
public InsertPersistenceOperation()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public InsertPersistenceOperation(ConversionService conversionService, ExpressionResolver expressionResolver)
|
||||
public InsertPersistenceOperation(ConversionService conversionService,
|
||||
ExpressionResolver variableExpressionResolver, ExpressionResolver sqlExpressionResolver)
|
||||
{
|
||||
super();
|
||||
this.conversionService = conversionService;
|
||||
this.expressionResolver = expressionResolver;
|
||||
}
|
||||
|
||||
public ConversionService getConversionService()
|
||||
{
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
public void setConversionService(ConversionService conversionService)
|
||||
{
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public ExpressionResolver getExpressionResolver()
|
||||
{
|
||||
return expressionResolver;
|
||||
}
|
||||
|
||||
public void setExpressionResolver(ExpressionResolver expressionResolver)
|
||||
{
|
||||
this.expressionResolver = expressionResolver;
|
||||
super(conversionService, variableExpressionResolver, sqlExpressionResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,7 +55,24 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
*/
|
||||
public int insert(Connection cn, Dialect dialect, String table, Model model, Object obj)
|
||||
{
|
||||
return insert(cn, dialect, table, model, obj, null, null, null, new HashMap<String, Object>());
|
||||
return insert(cn, dialect, table, model, obj, null, null, null, new ExpressionEvaluationContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入对象到指定表。
|
||||
*
|
||||
* @param cn
|
||||
* @param dialect
|
||||
* @param table
|
||||
* @param model
|
||||
* @param obj
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
public int insert(Connection cn, Dialect dialect, String table, Model model, Object obj,
|
||||
ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
return insert(cn, dialect, table, model, obj, null, null, null, expressionEvaluationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,15 +86,34 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* @param property
|
||||
* @param relationMapper
|
||||
* @param propertyValue
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @return
|
||||
*/
|
||||
public int insertPropertyTableData(Connection cn, Dialect dialect, String table, Model model, Object obj,
|
||||
Property property, Object propertyValue)
|
||||
{
|
||||
return insertPropertyTableData(cn, dialect, table, model, obj, property, getRelationMapper(model, property),
|
||||
propertyValue, new HashMap<String, Object>());
|
||||
propertyValue, new ExpressionEvaluationContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入属性表数据。
|
||||
*
|
||||
* @param cn
|
||||
* @param dialect
|
||||
* @param table
|
||||
* @param model
|
||||
* @param obj
|
||||
* @param property
|
||||
* @param relationMapper
|
||||
* @param propertyValue
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
public int insertPropertyTableData(Connection cn, Dialect dialect, String table, Model model, Object obj,
|
||||
Property property, Object propertyValue, ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
return insertPropertyTableData(cn, dialect, table, model, obj, property, getRelationMapper(model, property),
|
||||
propertyValue, expressionEvaluationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,18 +130,17 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* 附加列值,允许为{@code null}
|
||||
* @param ignorePropertyName
|
||||
* 忽略的属性名称,用于处理双向关联时,允许为{@code null}
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
*
|
||||
*/
|
||||
protected int insert(Connection cn, Dialect dialect, String table, Model model, Object obj,
|
||||
String[] extraColumnNames, Object[] extraColumnValues, String ignorePropertyName,
|
||||
Map<String, Object> expressionValueCache)
|
||||
ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
int count = insertModelTableData(cn, dialect, table, model, obj, extraColumnNames, extraColumnValues,
|
||||
ignorePropertyName, expressionValueCache);
|
||||
ignorePropertyName, expressionEvaluationContext);
|
||||
|
||||
insertPropertyTableData(cn, dialect, table, model, obj, ignorePropertyName, expressionValueCache);
|
||||
insertPropertyTableData(cn, dialect, table, model, obj, ignorePropertyName, expressionEvaluationContext);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -155,13 +162,12 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* 附加列值,允许为{@code null}
|
||||
* @param ignorePropertyName
|
||||
* 忽略的属性名称,允许为{@code null}
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
*
|
||||
*/
|
||||
protected int insertModelTableData(Connection cn, Dialect dialect, String table, Model model, Object obj,
|
||||
String[] extraColumnNames, Object[] extraColumnValues, String ignorePropertyName,
|
||||
Map<String, Object> expressionValueCache)
|
||||
ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
Property[] properties = model.getProperties();
|
||||
Object[] propertyValues = MU.getPropertyValues(model, obj, properties);
|
||||
|
@ -179,14 +185,14 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
|
||||
Object propertyValue = propertyValues[i];
|
||||
|
||||
List<Expression> expressions = this.expressionResolver.resolve(propertyValue);
|
||||
if (expressions != null && !expressions.isEmpty())
|
||||
{
|
||||
propertyValue = evaluatePropertyValueForQueryExpressions(cn, model, property, (String) propertyValue,
|
||||
expressions, expressionValueCache, this.conversionService, this.expressionResolver);
|
||||
Object evalPropertyValue = evaluatePropertyValueIfExpression(cn, model, property, propertyValue,
|
||||
expressionEvaluationContext);
|
||||
|
||||
propertyValues[i] = propertyValue;
|
||||
property.set(obj, propertyValue);
|
||||
if (evalPropertyValue != propertyValue)
|
||||
{
|
||||
propertyValue = evalPropertyValue;
|
||||
propertyValues[i] = evalPropertyValue;
|
||||
property.set(obj, evalPropertyValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,11 +281,10 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* @param obj
|
||||
* @param ignorePropertyName
|
||||
* 忽略的属性名称,用于处理双向关联时,允许为{@code null}
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
*/
|
||||
protected void insertPropertyTableData(Connection cn, Dialect dialect, String table, Model model, Object obj,
|
||||
String ignorePropertyName, Map<String, Object> expressionValueCache)
|
||||
String ignorePropertyName, ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
Property[] properties = model.getProperties();
|
||||
|
||||
|
@ -295,7 +300,7 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
continue;
|
||||
|
||||
insertPropertyTableData(cn, dialect, table, model, obj, property, getRelationMapper(model, property),
|
||||
propertyValue, expressionValueCache);
|
||||
propertyValue, expressionEvaluationContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,17 +315,16 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* @param property
|
||||
* @param relationMapper
|
||||
* @param propertyValue
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
protected int insertPropertyTableData(Connection cn, Dialect dialect, String table, Model model, Object obj,
|
||||
Property property, RelationMapper relationMapper, Object propertyValue,
|
||||
Map<String, Object> expressionValueCache)
|
||||
ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (this.expressionResolver.isExpression(propertyValue))
|
||||
if (isExpression(propertyValue))
|
||||
{
|
||||
return PERSISTENCE_IGNORED;
|
||||
}
|
||||
|
@ -330,7 +334,7 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
propertyValue);
|
||||
|
||||
return insertPropertyTableData(cn, dialect, table, model, obj, property, propertyModelMapper,
|
||||
toArray(propertyValue), null, expressionValueCache);
|
||||
toArray(propertyValue), null, expressionEvaluationContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -351,7 +355,7 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
|
||||
int myCount = insertPropertyTableData(cn, dialect, table, model, obj, property,
|
||||
PropertyModelMapper.valueOf(property, relationMapper, propertyModel), myPropValues,
|
||||
myPropValueIdexes, expressionValueCache);
|
||||
myPropValueIdexes, expressionEvaluationContext);
|
||||
|
||||
if (myCount > 0)
|
||||
count += myCount;
|
||||
|
@ -374,12 +378,11 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* @param propValues
|
||||
* @param propValueOrders
|
||||
* 允许为{@code null}
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
*/
|
||||
protected int insertPropertyTableData(Connection cn, Dialect dialect, String table, Model model, Object obj,
|
||||
Property property, PropertyModelMapper<?> propertyModelMapper, Object[] propValues, long[] propValueOrders,
|
||||
Map<String, Object> expressionValueCache)
|
||||
ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
if (propertyModelMapper.isModelTableMapperInfo())
|
||||
{
|
||||
|
@ -396,21 +399,21 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
throw new IllegalArgumentException();
|
||||
|
||||
return insertPropertyTableDataForCompositeModelTableMapper(cn, dialect, table, model, obj, property, mpmm,
|
||||
propValues[0], expressionValueCache);
|
||||
propValues[0], expressionEvaluationContext);
|
||||
}
|
||||
else if (propertyModelMapper.isPropertyTableMapperInfo())
|
||||
{
|
||||
PropertyModelMapper<PropertyTableMapper> ppmm = propertyModelMapper.castPropertyTableMapperInfo();
|
||||
|
||||
return insertPropertyTableDataForPropertyTableMapper(cn, dialect, table, model, obj, property, ppmm,
|
||||
propValues, propValueOrders, expressionValueCache);
|
||||
propValues, propValueOrders, expressionEvaluationContext);
|
||||
}
|
||||
else if (propertyModelMapper.isJoinTableMapperInfo())
|
||||
{
|
||||
PropertyModelMapper<JoinTableMapper> jpmm = propertyModelMapper.castJoinTableMapperInfo();
|
||||
|
||||
return insertPropertyTableDataForJoinTableMapper(cn, dialect, table, model, obj, property, jpmm, propValues,
|
||||
propValueOrders, expressionValueCache);
|
||||
propValueOrders, expressionEvaluationContext);
|
||||
}
|
||||
else
|
||||
throw new UnsupportedOperationException();
|
||||
|
@ -427,13 +430,12 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* @param property
|
||||
* @param propertyModelMapper
|
||||
* @param propValue
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
*
|
||||
*/
|
||||
protected int insertPropertyTableDataForCompositeModelTableMapper(Connection cn, Dialect dialect, String table,
|
||||
Model model, Object obj, Property property, PropertyModelMapper<ModelTableMapper> propertyModelMapper,
|
||||
Object propValue, Map<String, Object> expressionValueCache)
|
||||
Object propValue, ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
Model propertyModel = propertyModelMapper.getModel();
|
||||
|
||||
|
@ -441,7 +443,7 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
return PERSISTENCE_IGNORED;
|
||||
|
||||
return insert(cn, dialect, getTableName(propertyModel), propertyModel, propValue, null, null, null,
|
||||
expressionValueCache);
|
||||
expressionEvaluationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -457,25 +459,24 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* @param propValues
|
||||
* @param propValueOrders
|
||||
* 允许为{@code null}
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
protected int insertPropertyTableDataForPropertyTableMapper(Connection cn, Dialect dialect, String table,
|
||||
Model model, Object obj, Property property, PropertyModelMapper<PropertyTableMapper> propertyModelMapper,
|
||||
Object[] propValues, long[] propValueOrders, Map<String, Object> expressionValueCache)
|
||||
Object[] propValues, long[] propValueOrders, ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
PropertyTableMapper mapper = propertyModelMapper.getMapper();
|
||||
|
||||
if (mapper.isPrimitivePropertyMapper())
|
||||
{
|
||||
return insertPropertyTableDataForPrimitiveValuePropertyTableMapper(cn, dialect, table, model, obj, property,
|
||||
propertyModelMapper, propValues, propValueOrders, expressionValueCache);
|
||||
propertyModelMapper, propValues, propValueOrders, expressionEvaluationContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
return insertPropertyTableDataForCompositePropertyTableMapper(cn, dialect, table, model, obj, property,
|
||||
propertyModelMapper, propValues, propValueOrders, expressionValueCache);
|
||||
propertyModelMapper, propValues, propValueOrders, expressionEvaluationContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,14 +493,13 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* @param propValues
|
||||
* @param propValueOrders
|
||||
* 允许为{@code null}
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
*
|
||||
*/
|
||||
protected int insertPropertyTableDataForPrimitiveValuePropertyTableMapper(Connection cn, Dialect dialect,
|
||||
String table, Model model, Object obj, Property property,
|
||||
PropertyModelMapper<PropertyTableMapper> propertyModelMapper, Object[] propValues, long[] propValueOrders,
|
||||
Map<String, Object> expressionValueCache)
|
||||
ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
|
@ -531,11 +531,13 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
{
|
||||
Object propertyValue = propValues[i];
|
||||
|
||||
List<Expression> expressions = this.expressionResolver.resolve(propertyValue);
|
||||
if (expressions != null && !expressions.isEmpty())
|
||||
Object evalPropertyValue = evaluatePropertyValueIfExpression(cn, model, property, propertyValue,
|
||||
expressionEvaluationContext);
|
||||
|
||||
if (evalPropertyValue != propertyValue)
|
||||
{
|
||||
propertyValue = evaluatePropertyValueForQueryExpressions(cn, model, property, (String) propertyValue,
|
||||
expressions, expressionValueCache, this.conversionService, this.expressionResolver);
|
||||
propertyValue = evalPropertyValue;
|
||||
propValues[i] = evalPropertyValue;
|
||||
}
|
||||
|
||||
Object columnValue = getColumnValue(cn, model, property, propertyModelMapper, propertyValue);
|
||||
|
@ -569,13 +571,12 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* @param propValues
|
||||
* @param propValueOrders
|
||||
* 允许为{@code null}
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
protected int insertPropertyTableDataForCompositePropertyTableMapper(Connection cn, Dialect dialect, String table,
|
||||
Model model, Object obj, Property property, PropertyModelMapper<PropertyTableMapper> propertyModelMapper,
|
||||
Object[] propValues, long[] propValueOrders, Map<String, Object> expressionValueCache)
|
||||
Object[] propValues, long[] propValueOrders, ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
|
@ -596,7 +597,7 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
(propValueOrders == null ? null : propValueOrders[i]));
|
||||
|
||||
int myCount = insert(cn, dialect, ptable, propertyModel, propValues[i], allMapperColumNames,
|
||||
allMapperColumnValues, getMappedByWith(mapper), expressionValueCache);
|
||||
allMapperColumnValues, getMappedByWith(mapper), expressionEvaluationContext);
|
||||
|
||||
if (myCount > 0)
|
||||
count += myCount;
|
||||
|
@ -693,13 +694,12 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* @param propValues
|
||||
* @param propValueOrders
|
||||
* 允许为{@code null}
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
*
|
||||
*/
|
||||
protected int insertPropertyTableDataForJoinTableMapper(Connection cn, Dialect dialect, String table, Model model,
|
||||
Object obj, Property property, PropertyModelMapper<JoinTableMapper> propertyModelMapper,
|
||||
Object[] propValues, long[] propValueOrders, Map<String, Object> expressionValueCache)
|
||||
Object[] propValues, long[] propValueOrders, ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
Model propertyModel = propertyModelMapper.getModel();
|
||||
|
||||
|
@ -709,7 +709,8 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
{
|
||||
if (PMU.isPrivate(model, property, propertyModel))
|
||||
{
|
||||
insert(cn, dialect, ptable, propertyModel, propValues[i], null, null, null, expressionValueCache);
|
||||
insert(cn, dialect, ptable, propertyModel, propValues[i], null, null, null,
|
||||
expressionEvaluationContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -844,7 +845,7 @@ public class InsertPersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
if (valueGenerator != null)
|
||||
propValue = valueGenerator.generate(model, property, obj);
|
||||
|
||||
if (propValue != null && this.expressionResolver.isExpression(propValue))
|
||||
if (propValue != null && isExpression(propValue))
|
||||
property.set(obj, propValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ package org.datagear.persistence.support;
|
|||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.datagear.persistence.PersistenceException;
|
||||
import org.datagear.persistence.support.ExpressionResolver.Expression;
|
||||
|
||||
/**
|
||||
|
@ -15,20 +14,12 @@ import org.datagear.persistence.support.ExpressionResolver.Expression;
|
|||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class SqlExpressionErrorException extends PersistenceException
|
||||
public class SqlExpressionErrorException extends ExpressionErrorException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Expression expression;
|
||||
|
||||
public SqlExpressionErrorException(Expression expression, SQLException cause)
|
||||
{
|
||||
super(expression.getContent(), cause);
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
public Expression getExpression()
|
||||
{
|
||||
return expression;
|
||||
super(expression, cause);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2018 datagear.org. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package org.datagear.persistence.support;
|
||||
|
||||
/**
|
||||
* SQL表达式解析器。
|
||||
* <p>
|
||||
* 此类将表达式格式固化为<code>${name:value}、${value}</code>,用于解析SQL表达式。
|
||||
* </p>
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class SqlExpressionResolver extends ExpressionResolver
|
||||
{
|
||||
public SqlExpressionResolver()
|
||||
{
|
||||
super();
|
||||
super.setStartIdentifier(DEFAULT_START_IDENTIFIER_DOLLAR);
|
||||
super.setSeparator(DEFAULT_SEPARATOR);
|
||||
super.setEndIdentifier(DEFAULT_END_IDENTIFIER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStartIdentifier(String startIdentifier)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEndIdentifier(String endIdentifier)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSeparator(String separator)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
|
@ -6,9 +6,7 @@ package org.datagear.persistence.support;
|
|||
|
||||
import java.sql.Connection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.datagear.model.Model;
|
||||
import org.datagear.model.Property;
|
||||
|
@ -24,7 +22,6 @@ import org.datagear.persistence.mapper.ModelTableMapper;
|
|||
import org.datagear.persistence.mapper.PropertyModelMapper;
|
||||
import org.datagear.persistence.mapper.PropertyTableMapper;
|
||||
import org.datagear.persistence.mapper.RelationMapper;
|
||||
import org.datagear.persistence.support.ExpressionResolver.Expression;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
|
||||
/**
|
||||
|
@ -33,7 +30,7 @@ import org.springframework.core.convert.ConversionService;
|
|||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class UpdatePersistenceOperation extends AbstractModelPersistenceOperation
|
||||
public class UpdatePersistenceOperation extends AbstractExpressionModelPersistenceOperation
|
||||
{
|
||||
/** 当记录未做修改时,返回此标识 */
|
||||
public static final int UNCHANGED = PERSISTENCE_IGNORED - 1;
|
||||
|
@ -45,10 +42,6 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
|
||||
private DeletePersistenceOperation deletePersistenceOperation;
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ExpressionResolver expressionResolver;
|
||||
|
||||
public UpdatePersistenceOperation()
|
||||
{
|
||||
super();
|
||||
|
@ -56,13 +49,11 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
|
||||
public UpdatePersistenceOperation(InsertPersistenceOperation insertPersistenceOperation,
|
||||
DeletePersistenceOperation deletePersistenceOperation, ConversionService conversionService,
|
||||
ExpressionResolver expressionResolver)
|
||||
ExpressionResolver variableExpressionResolver, ExpressionResolver sqlExpressionResolver)
|
||||
{
|
||||
super();
|
||||
super(conversionService, variableExpressionResolver, sqlExpressionResolver);
|
||||
this.insertPersistenceOperation = insertPersistenceOperation;
|
||||
this.deletePersistenceOperation = deletePersistenceOperation;
|
||||
this.conversionService = conversionService;
|
||||
this.expressionResolver = expressionResolver;
|
||||
}
|
||||
|
||||
public boolean isHandleMultipleProperty()
|
||||
|
@ -95,26 +86,6 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
this.deletePersistenceOperation = deletePersistenceOperation;
|
||||
}
|
||||
|
||||
public ConversionService getConversionService()
|
||||
{
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
public void setConversionService(ConversionService conversionService)
|
||||
{
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public ExpressionResolver getExpressionResolver()
|
||||
{
|
||||
return expressionResolver;
|
||||
}
|
||||
|
||||
public void setExpressionResolver(ExpressionResolver expressionResolver)
|
||||
{
|
||||
this.expressionResolver = expressionResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新。
|
||||
*
|
||||
|
@ -122,8 +93,6 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* @param dialect
|
||||
* @param table
|
||||
* @param model
|
||||
* @param originalCondition
|
||||
* 用于确定原始数据记录的模型表条件
|
||||
* @param originalObj
|
||||
* 原始数据
|
||||
* @param updateObj
|
||||
|
@ -135,7 +104,30 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
SqlBuilder originalCondition = buildRecordCondition(cn, dialect, model, originalObj, null);
|
||||
|
||||
return update(cn, dialect, table, model, originalCondition, originalObj, updateObj, null, null, null,
|
||||
new HashMap<String, Object>());
|
||||
new ExpressionEvaluationContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新。
|
||||
*
|
||||
* @param cn
|
||||
* @param dialect
|
||||
* @param table
|
||||
* @param model
|
||||
* @param originalObj
|
||||
* 原始数据
|
||||
* @param updateObj
|
||||
* 待更新的数据
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
public int update(Connection cn, Dialect dialect, String table, Model model, Object originalObj, Object updateObj,
|
||||
ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
SqlBuilder originalCondition = buildRecordCondition(cn, dialect, model, originalObj, null);
|
||||
|
||||
return update(cn, dialect, table, model, originalCondition, originalObj, updateObj, null, null, null,
|
||||
expressionEvaluationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,7 +151,32 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
Object updatePropertyValue)
|
||||
{
|
||||
return updatePropertyTableData(cn, dialect, table, model, condition, property, propertyModelMapper,
|
||||
originalPropertyValue, updatePropertyValue, null, true, new HashMap<String, Object>());
|
||||
originalPropertyValue, updatePropertyValue, null, true, new ExpressionEvaluationContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新属性表数据。
|
||||
*
|
||||
* @param cn
|
||||
* @param dialect
|
||||
* @param table
|
||||
* @param model
|
||||
* @param condition
|
||||
* @param property
|
||||
* @param propertyModelMapper
|
||||
* @param originalPropertyValue
|
||||
* 原始属性值
|
||||
* @param updatePropertyValue
|
||||
* 待更新的属性值,允许为{@code null}
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
public int updatePropertyTableData(Connection cn, Dialect dialect, String table, Model model, SqlBuilder condition,
|
||||
Property property, PropertyModelMapper<?> propertyModelMapper, Object originalPropertyValue,
|
||||
Object updatePropertyValue, ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
return updatePropertyTableData(cn, dialect, table, model, condition, property, propertyModelMapper,
|
||||
originalPropertyValue, updatePropertyValue, null, true, expressionEvaluationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,13 +198,12 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* 附加列值,允许为{@code null}
|
||||
* @param ignorePropertyName
|
||||
* 忽略的属性名称,用于处理双向关联时,允许为{@code null}
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
protected int update(Connection cn, Dialect dialect, String table, Model model, SqlBuilder originalCondition,
|
||||
Object originalObj, Object updateObj, String[] extraColumnNames, Object[] extraColumnValues,
|
||||
String ignorePropertyName, Map<String, Object> expressionValueCache)
|
||||
String ignorePropertyName, ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
|
@ -207,14 +223,14 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
|
||||
Object propertyValue = updatePropertyValues[i];
|
||||
|
||||
List<Expression> expressions = this.expressionResolver.resolve(propertyValue);
|
||||
if (expressions != null && !expressions.isEmpty())
|
||||
{
|
||||
propertyValue = evaluatePropertyValueForQueryExpressions(cn, model, property, (String) propertyValue,
|
||||
expressions, expressionValueCache, this.conversionService, this.expressionResolver);
|
||||
Object evalPropertyValue = evaluatePropertyValueIfExpression(cn, model, property, propertyValue,
|
||||
expressionEvaluationContext);
|
||||
|
||||
updatePropertyValues[i] = propertyValue;
|
||||
property.set(updateObj, propertyValue);
|
||||
if (evalPropertyValue != propertyValue)
|
||||
{
|
||||
propertyValue = evalPropertyValue;
|
||||
updatePropertyValues[i] = evalPropertyValue;
|
||||
property.set(updateObj, evalPropertyValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,12 +284,12 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
{
|
||||
int myUpdateCount = updatePropertyTableData(cn, dialect, table, model, originalCondition,
|
||||
property, pmm, originalPropertyValue, updatePropertyValue, updateObj, false,
|
||||
expressionValueCache);
|
||||
expressionEvaluationContext);
|
||||
|
||||
if (myUpdateCount == 0)
|
||||
insertPersistenceOperation.insertPropertyTableData(cn, dialect, table, model, updateObj,
|
||||
property, pmm, new Object[] { updatePropertyValue }, null,
|
||||
expressionValueCache);
|
||||
expressionEvaluationContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -307,12 +323,12 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
int myUpdateCount = updatePropertyTableData(cn, dialect, table, model, updateCondition,
|
||||
updateInfo.getProperty(), updateInfo.getPropertyModelMapper(),
|
||||
originalPropertyValues[updateInfo.getPropertyIndex()], updatePropertyValue, null, false,
|
||||
expressionValueCache);
|
||||
expressionEvaluationContext);
|
||||
|
||||
if (myUpdateCount == 0)
|
||||
insertPersistenceOperation.insertPropertyTableData(cn, dialect, table, model, updateObj,
|
||||
updateInfo.getProperty(), updateInfo.getPropertyModelMapper(),
|
||||
new Object[] { updatePropertyValue }, null, expressionValueCache);
|
||||
new Object[] { updatePropertyValue }, null, expressionEvaluationContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,14 +443,13 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* 需要处理外键更新的对象,允许为{@code null}
|
||||
* @param updateModelTable
|
||||
* 是否更新模型表数据
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
protected int updatePropertyTableData(Connection cn, Dialect dialect, String table, Model model,
|
||||
SqlBuilder condition, Property property, PropertyModelMapper<?> propertyModelMapper,
|
||||
Object originalPropertyValue, Object updatePropertyValue, Object keyUpdateObj, boolean updateModelTable,
|
||||
Map<String, Object> expressionValueCache)
|
||||
ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
|
@ -443,21 +458,21 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
PropertyModelMapper<ModelTableMapper> mpmm = propertyModelMapper.castModelTableMapperInfo();
|
||||
|
||||
count = updatePropertyTableDataForModelTableMapper(cn, dialect, table, model, condition, property, mpmm,
|
||||
originalPropertyValue, updatePropertyValue, updateModelTable, expressionValueCache);
|
||||
originalPropertyValue, updatePropertyValue, updateModelTable, expressionEvaluationContext);
|
||||
}
|
||||
else if (propertyModelMapper.isPropertyTableMapperInfo())
|
||||
{
|
||||
PropertyModelMapper<PropertyTableMapper> ppmm = propertyModelMapper.castPropertyTableMapperInfo();
|
||||
|
||||
count = updatePropertyTableDataForPropertyTableMapper(cn, dialect, table, model, condition, property, ppmm,
|
||||
originalPropertyValue, updatePropertyValue, keyUpdateObj, expressionValueCache);
|
||||
originalPropertyValue, updatePropertyValue, keyUpdateObj, expressionEvaluationContext);
|
||||
}
|
||||
else if (propertyModelMapper.isJoinTableMapperInfo())
|
||||
{
|
||||
PropertyModelMapper<JoinTableMapper> jpmm = propertyModelMapper.castJoinTableMapperInfo();
|
||||
|
||||
count = updatePropertyTableDataForJoinTableMapper(cn, dialect, table, model, condition, property, jpmm,
|
||||
originalPropertyValue, updatePropertyValue, keyUpdateObj, expressionValueCache);
|
||||
originalPropertyValue, updatePropertyValue, keyUpdateObj, expressionEvaluationContext);
|
||||
}
|
||||
else
|
||||
throw new UnsupportedOperationException();
|
||||
|
@ -482,14 +497,13 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* 待更新的属性值,允许为{@code null}
|
||||
* @param updateModelTable
|
||||
* 是否更新模型表数据
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
protected int updatePropertyTableDataForModelTableMapper(Connection cn, Dialect dialect, String table, Model model,
|
||||
SqlBuilder condition, Property property, PropertyModelMapper<ModelTableMapper> propertyModelMapper,
|
||||
Object originalPropertyValue, Object updatePropertyValue, boolean updateModelTable,
|
||||
Map<String, Object> expressionValueCache)
|
||||
ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
|
@ -519,7 +533,7 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
{
|
||||
count = update(cn, dialect, table, pmodel,
|
||||
buildRecordCondition(cn, dialect, pmodel, originalPropertyValue, null), originalPropertyValue,
|
||||
updatePropertyValue, null, null, getMappedByWith(mapper), expressionValueCache);
|
||||
updatePropertyValue, null, null, getMappedByWith(mapper), expressionEvaluationContext);
|
||||
|
||||
if (updateModelTable)
|
||||
{
|
||||
|
@ -571,14 +585,13 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* 待更新的属性值,允许为{@code null}
|
||||
* @param keyUpdateObj
|
||||
* 需要处理外键更新的对象,允许为{@code null}
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
protected int updatePropertyTableDataForPropertyTableMapper(Connection cn, Dialect dialect, String table,
|
||||
Model model, SqlBuilder condition, Property property,
|
||||
PropertyModelMapper<PropertyTableMapper> propertyModelMapper, Object originalPropertyValue,
|
||||
Object updatePropertyValue, Object keyUpdateObj, Map<String, Object> expressionValueCache)
|
||||
Object updatePropertyValue, Object keyUpdateObj, ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
|
@ -621,15 +634,14 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
{
|
||||
String columnName = toQuoteName(dialect, mapper.getPrimitiveColumnName());
|
||||
|
||||
List<Expression> expressions = this.expressionResolver.resolve(updatePropertyValue);
|
||||
if (expressions != null && !expressions.isEmpty())
|
||||
{
|
||||
updatePropertyValue = evaluatePropertyValueForQueryExpressions(cn, model, property,
|
||||
(String) updatePropertyValue, expressions, expressionValueCache, this.conversionService,
|
||||
this.expressionResolver);
|
||||
Object evalUpdatePropertyValue = evaluatePropertyValueIfExpression(cn, model, property,
|
||||
updatePropertyValue, expressionEvaluationContext);
|
||||
|
||||
if (evalUpdatePropertyValue != updatePropertyValue)
|
||||
{
|
||||
updatePropertyValue = evalUpdatePropertyValue;
|
||||
Object columnValue = getColumnValue(cn, model, property, propertyModelMapper,
|
||||
updatePropertyValue);
|
||||
evalUpdatePropertyValue);
|
||||
|
||||
sql.sqldSuffix(columnName, "=" + columnValue);
|
||||
}
|
||||
|
@ -653,7 +665,7 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
{
|
||||
count = update(cn, dialect, getTableName(propertyModel), propertyModel, ptableCondition,
|
||||
originalPropertyValue, updatePropertyValue, mkeyColumnNames, mkeyColumnValues,
|
||||
getMappedByWith(propertyModelMapper.getMapper()), expressionValueCache);
|
||||
getMappedByWith(propertyModelMapper.getMapper()), expressionEvaluationContext);
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -675,14 +687,13 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
* 待更新的属性值,允许为{@code null}
|
||||
* @param keyUpdateObj
|
||||
* 需要处理外键更新的对象,允许为{@code null}
|
||||
* @param expressionValueCache
|
||||
* 用于缓存SQL表达式求值结果的映射表
|
||||
* @param expressionEvaluationContext
|
||||
* @return
|
||||
*/
|
||||
protected int updatePropertyTableDataForJoinTableMapper(Connection cn, Dialect dialect, String table, Model model,
|
||||
SqlBuilder condition, Property property, PropertyModelMapper<JoinTableMapper> propertyModelMapper,
|
||||
Object originalPropertyValue, Object updatePropertyValue, Object keyUpdateObj,
|
||||
Map<String, Object> expressionValueCache)
|
||||
ExpressionEvaluationContext expressionEvaluationContext)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
|
@ -701,7 +712,7 @@ public class UpdatePersistenceOperation extends AbstractModelPersistenceOperatio
|
|||
{
|
||||
count = update(cn, dialect, getTableName(propertyModel), propertyModel, ptableCondition,
|
||||
originalPropertyValue, updatePropertyValue, null, null,
|
||||
getMappedByWith(propertyModelMapper.getMapper()), expressionValueCache);
|
||||
getMappedByWith(propertyModelMapper.getMapper()), expressionEvaluationContext);
|
||||
|
||||
if (keyUpdateObj != null)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2018 datagear.org. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package org.datagear.persistence.support;
|
||||
|
||||
/**
|
||||
* 用于变量表达式求值的Bean。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class VariableExpressionBean
|
||||
{
|
||||
private int index;
|
||||
|
||||
public VariableExpressionBean()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public VariableExpressionBean(int index)
|
||||
{
|
||||
super();
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public int getIndex()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index)
|
||||
{
|
||||
this.index = index;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2018 datagear.org. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package org.datagear.persistence.support;
|
||||
|
||||
import org.datagear.persistence.support.ExpressionResolver.Expression;
|
||||
|
||||
/**
|
||||
* 变量表达式执行出错。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class VariableExpressionErrorException extends ExpressionErrorException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public VariableExpressionErrorException(Expression expression, Exception cause)
|
||||
{
|
||||
super(expression, cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2018 datagear.org. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package org.datagear.persistence.support;
|
||||
|
||||
/**
|
||||
* 变量表达式解析器。
|
||||
* <p>
|
||||
* 此类将表达式格式固化为<code>#{name:value}、#{value}</code>,用于解析变量表达式。
|
||||
* </p>
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class VariableExpressionResolver extends ExpressionResolver
|
||||
{
|
||||
public VariableExpressionResolver()
|
||||
{
|
||||
super();
|
||||
super.setStartIdentifier(DEFAULT_START_IDENTIFIER_SHARP);
|
||||
super.setSeparator(DEFAULT_SEPARATOR);
|
||||
super.setEndIdentifier(DEFAULT_END_IDENTIFIER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStartIdentifier(String startIdentifier)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEndIdentifier(String endIdentifier)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSeparator(String separator)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
|
@ -13,12 +13,12 @@ import org.junit.Test;
|
|||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class AbstractModelPersistenceOperationTest
|
||||
public class AbstractExpressionModelPersistenceOperationTest
|
||||
{
|
||||
@Test
|
||||
public void isSelectSqlTest()
|
||||
{
|
||||
AbstractModelPersistenceOperation persistenceOperation = new AbstractModelPersistenceOperation()
|
||||
AbstractExpressionModelPersistenceOperation persistenceOperation = new AbstractExpressionModelPersistenceOperation()
|
||||
{
|
||||
};
|
||||
|
|
@ -169,6 +169,21 @@ public class ExpressionResolverTest
|
|||
Assert.assertEquals("content2", e.getContent());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
List<Expression> expressions = expressionResolver.resolve("prefix\\${content0}");
|
||||
|
||||
Assert.assertEquals(0, expressions.size());
|
||||
}
|
||||
|
||||
{
|
||||
List<Expression> expressions = expressionResolver.resolve("prefix${cont\\:ent\\}0}");
|
||||
|
||||
Assert.assertEquals(1, expressions.size());
|
||||
|
||||
Expression e = expressions.get(0);
|
||||
Assert.assertEquals("cont:ent}0", e.getContent());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2018 datagear.org. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package org.datagear.persistence.support;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
|
||||
/**
|
||||
* {@linkplain SpelExpressionParser}测试类。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class SpelExpressionParserTest
|
||||
{
|
||||
private SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
|
||||
|
||||
@Test
|
||||
public void test()
|
||||
{
|
||||
{
|
||||
int value = (Integer) spelExpressionParser.parseExpression("index").getValue(new TestBean());
|
||||
Assert.assertEquals(0, value);
|
||||
}
|
||||
|
||||
{
|
||||
int value = (Integer) spelExpressionParser.parseExpression("index").getValue(new TestBean(2));
|
||||
Assert.assertEquals(2, value);
|
||||
}
|
||||
|
||||
{
|
||||
int value = (Integer) spelExpressionParser.parseExpression("index * 5").getValue(new TestBean(2));
|
||||
Assert.assertEquals(10, value);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class TestBean
|
||||
{
|
||||
private int index;
|
||||
|
||||
public TestBean()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public TestBean(int index)
|
||||
{
|
||||
super();
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public int getIndex()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index)
|
||||
{
|
||||
this.index = index;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ import org.datagear.dbmodel.DatabaseModelResolverException;
|
|||
import org.datagear.persistence.PersistenceException;
|
||||
import org.datagear.persistence.UnsupportedDialectException;
|
||||
import org.datagear.persistence.support.SqlExpressionErrorException;
|
||||
import org.datagear.persistence.support.VariableExpressionErrorException;
|
||||
import org.datagear.web.convert.IllegalSourceValueException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.validation.BindException;
|
||||
|
@ -50,7 +51,8 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleControllerMissingServletRequestParameterException(HttpServletRequest request,
|
||||
HttpServletResponse response, MissingServletRequestParameterException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(MissingServletRequestParameterException.class),
|
||||
exception, false);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -60,7 +62,7 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleControllerBindException(HttpServletRequest request, HttpServletResponse response,
|
||||
BindException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(BindException.class), exception, false);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -70,7 +72,8 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleControllerMethodArgumentNotValidException(HttpServletRequest request,
|
||||
HttpServletResponse response, MethodArgumentNotValidException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(MethodArgumentNotValidException.class), exception,
|
||||
false);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -80,7 +83,8 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleAuthenticationFailedException(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationFailedException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, true);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(AuthenticationFailedException.class), exception,
|
||||
true);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -90,7 +94,7 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleControllerIllegalInputException(HttpServletRequest request, HttpServletResponse response,
|
||||
IllegalInputException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(IllegalInputException.class), exception, false);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -100,7 +104,7 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleControllerRecordNotFoundException(HttpServletRequest request, HttpServletResponse response,
|
||||
RecordNotFoundException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(RecordNotFoundException.class), exception, false);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -110,7 +114,8 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleControllerRecordNotFoundOrNoPermissionException(HttpServletRequest request,
|
||||
HttpServletResponse response, RecordNotFoundOrPermissionDeniedException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(RecordNotFoundOrPermissionDeniedException.class),
|
||||
exception, false);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -120,7 +125,7 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleControllerSchemaNotFoundException(HttpServletRequest request, HttpServletResponse response,
|
||||
SchemaNotFoundException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(SchemaNotFoundException.class), exception, false);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -130,8 +135,8 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleControllerIllegalSourceValueException(HttpServletRequest request, HttpServletResponse response,
|
||||
IllegalSourceValueException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false, exception.getSourceValue(),
|
||||
exception.getTargetType().getName());
|
||||
setOperationMessageForThrowable(request, buildMessageCode(IllegalSourceValueException.class), exception, false,
|
||||
exception.getSourceValue(), exception.getTargetType().getName());
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -141,7 +146,19 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleControllerFileNotFoundException(HttpServletRequest request, HttpServletResponse response,
|
||||
FileNotFoundException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false, exception.getFileName());
|
||||
setOperationMessageForThrowable(request, buildMessageCode(FileNotFoundException.class), exception, false,
|
||||
exception.getFileName());
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
||||
@ExceptionHandler(VariableExpressionErrorException.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public String handlePersistenceVariableExpressionErrorException(HttpServletRequest request,
|
||||
HttpServletResponse response, VariableExpressionErrorException exception)
|
||||
{
|
||||
setOperationMessageForThrowable(request, buildMessageCode(VariableExpressionErrorException.class),
|
||||
exception.getCause(), false, exception.getExpression().getContent());
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -151,7 +168,8 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handlePersistenceSqlExpressionErrorException(HttpServletRequest request, HttpServletResponse response,
|
||||
SqlExpressionErrorException exception)
|
||||
{
|
||||
setOperationMessageForExceptionCause(request, exception);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(SqlExpressionErrorException.class),
|
||||
exception.getCause(), true, exception.getExpression().getContent());
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -161,7 +179,7 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handlePersistenceUnsupportedDialectException(HttpServletRequest request, HttpServletResponse response,
|
||||
UnsupportedDialectException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(UnsupportedDialectException.class), exception, false);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -172,9 +190,10 @@ public class ControllerAdvice extends AbstractController
|
|||
PersistenceException exception)
|
||||
{
|
||||
if (exception.getCause() instanceof SQLException)
|
||||
setOperationMessageForExceptionCause(request, exception);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(PersistenceException.class), exception.getCause(),
|
||||
true);
|
||||
else
|
||||
setOperationMessageForException(request, exception, true);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(PersistenceException.class), exception, true);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -184,7 +203,8 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleDbmodelDatabaseInfoResolverException(HttpServletRequest request, HttpServletResponse response,
|
||||
DatabaseInfoResolverException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, true);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(DatabaseInfoResolverException.class), exception,
|
||||
true);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -194,7 +214,8 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleDbmodelDatabaseModelResolverException(HttpServletRequest request, HttpServletResponse response,
|
||||
DatabaseModelResolverException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, true);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(DatabaseModelResolverException.class), exception,
|
||||
true);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -204,7 +225,8 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleDbmodelTableNotExistsException(HttpServletRequest request, HttpServletResponse response,
|
||||
TableNotExistsException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false, exception.getTableName());
|
||||
setOperationMessageForThrowable(request, buildMessageCode(TableNotExistsException.class), exception, false,
|
||||
exception.getTableName());
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -214,7 +236,7 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleConnectionConnectionSourceException(HttpServletRequest request, HttpServletResponse response,
|
||||
ConnectionSourceException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, true);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(ConnectionSourceException.class), exception, true);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -224,7 +246,7 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleConnectionDriverEntityManagerException(HttpServletRequest request, HttpServletResponse response,
|
||||
DriverEntityManagerException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, true);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(DriverEntityManagerException.class), exception, true);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -234,7 +256,8 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleConnectionDriverNotFoundException(HttpServletRequest request, HttpServletResponse response,
|
||||
DriverNotFoundException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false, exception.getDriverClassName());
|
||||
setOperationMessageForThrowable(request, buildMessageCode(DriverNotFoundException.class), exception, false,
|
||||
exception.getDriverClassName());
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -244,7 +267,8 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleConnectionDriverClassFormatErrorException(HttpServletRequest request,
|
||||
HttpServletResponse response, DriverClassFormatErrorException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(DriverClassFormatErrorException.class), exception,
|
||||
false);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -254,7 +278,7 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleConnectionURLNotAcceptedException(HttpServletRequest request, HttpServletResponse response,
|
||||
URLNotAcceptedException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(URLNotAcceptedException.class), exception, false);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -264,7 +288,8 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleConnectionUnsupportedGetConnectionException(HttpServletRequest request,
|
||||
HttpServletResponse response, UnsupportedGetConnectionException exception)
|
||||
{
|
||||
setOperationMessageForException(request, exception, false);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(UnsupportedGetConnectionException.class), exception,
|
||||
false);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
@ -274,25 +299,15 @@ public class ControllerAdvice extends AbstractController
|
|||
public String handleConnectionEstablishConnectionException(HttpServletRequest request, HttpServletResponse response,
|
||||
EstablishConnectionException exception)
|
||||
{
|
||||
setOperationMessageForExceptionCause(request, exception);
|
||||
setOperationMessageForThrowable(request, buildMessageCode(EstablishConnectionException.class),
|
||||
exception.getCause(), true);
|
||||
|
||||
return ERROR_PAGE_URL;
|
||||
}
|
||||
|
||||
protected void setOperationMessageForException(HttpServletRequest request, Exception exception,
|
||||
boolean traceException, Object... messageArgs)
|
||||
protected String buildMessageCode(Class<? extends Throwable> clazz)
|
||||
{
|
||||
String code = buildMessageCode(exception.getClass().getSimpleName());
|
||||
|
||||
setOperationMessageForThrowable(request, code, exception, traceException, messageArgs);
|
||||
}
|
||||
|
||||
protected void setOperationMessageForExceptionCause(HttpServletRequest request, Exception exception,
|
||||
Object... messageArgs)
|
||||
{
|
||||
String code = buildMessageCode(exception.getClass().getSimpleName());
|
||||
|
||||
setOperationMessageForThrowable(request, code, exception.getCause(), true, messageArgs);
|
||||
return buildMessageCode(clazz.getSimpleName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -33,6 +33,8 @@ import org.datagear.model.support.DefaultDynamicBean;
|
|||
import org.datagear.model.support.DynamicBean;
|
||||
import org.datagear.model.support.PropertyPath;
|
||||
import org.datagear.persistence.support.ExpressionResolver;
|
||||
import org.datagear.persistence.support.SqlExpressionResolver;
|
||||
import org.datagear.persistence.support.VariableExpressionResolver;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
|
||||
/**
|
||||
|
@ -64,7 +66,9 @@ public abstract class AbstractDataConverter
|
|||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private ExpressionResolver expressionResolver = new ExpressionResolver();
|
||||
private ExpressionResolver variableExpressionResolver = new VariableExpressionResolver();
|
||||
|
||||
private ExpressionResolver sqlExpressionResolver = new SqlExpressionResolver();
|
||||
|
||||
private Map<Class<?>, Class<?>> instanceTypeMap = new HashMap<Class<?>, Class<?>>();
|
||||
|
||||
|
@ -91,14 +95,24 @@ public abstract class AbstractDataConverter
|
|||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public ExpressionResolver getExpressionResolver()
|
||||
public ExpressionResolver getVariableExpressionResolver()
|
||||
{
|
||||
return expressionResolver;
|
||||
return variableExpressionResolver;
|
||||
}
|
||||
|
||||
public void setExpressionResolver(ExpressionResolver expressionResolver)
|
||||
public void setVariableExpressionResolver(ExpressionResolver variableExpressionResolver)
|
||||
{
|
||||
this.expressionResolver = expressionResolver;
|
||||
this.variableExpressionResolver = variableExpressionResolver;
|
||||
}
|
||||
|
||||
public ExpressionResolver getSqlExpressionResolver()
|
||||
{
|
||||
return sqlExpressionResolver;
|
||||
}
|
||||
|
||||
public void setSqlExpressionResolver(ExpressionResolver sqlExpressionResolver)
|
||||
{
|
||||
this.sqlExpressionResolver = sqlExpressionResolver;
|
||||
}
|
||||
|
||||
public Map<Class<?>, Class<?>> getInstanceTypeMap()
|
||||
|
@ -167,7 +181,7 @@ public abstract class AbstractDataConverter
|
|||
{
|
||||
String str = (String) obj;
|
||||
|
||||
if (this.expressionResolver.isExpression(str))
|
||||
if (isExpression(str))
|
||||
return (T) str;
|
||||
|
||||
if (str.isEmpty() && !String.class.equals(targetType))
|
||||
|
@ -385,6 +399,11 @@ public abstract class AbstractDataConverter
|
|||
return getInstanceType(instanceType);
|
||||
}
|
||||
|
||||
protected boolean isExpression(Object obj)
|
||||
{
|
||||
return this.variableExpressionResolver.isExpression(obj) || this.sqlExpressionResolver.isExpression(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较{@code "[xxx]"}格式字符串的大小。
|
||||
*
|
||||
|
|
|
@ -207,9 +207,15 @@
|
|||
|
||||
<bean id="selectOptions" class="org.datagear.persistence.support.SelectOptions" />
|
||||
|
||||
<bean id="variableExpressionResolver" class="org.datagear.persistence.support.VariableExpressionResolver" />
|
||||
|
||||
<bean id="sqlExpressionResolver" class="org.datagear.persistence.support.SqlExpressionResolver" />
|
||||
|
||||
<bean id="persistenceManager" class="org.datagear.persistence.support.DefaultPersistenceManager">
|
||||
<property name="dialectSource" ref="dialectSource" />
|
||||
<property name="conversionService" ref="conversionService" />
|
||||
<property name="variableExpressionResolver" ref="variableExpressionResolver" />
|
||||
<property name="sqlExpressionResolver" ref="sqlExpressionResolver" />
|
||||
<property name="selectPersistenceOperation">
|
||||
<bean class="org.datagear.persistence.support.SelectPersistenceOperation">
|
||||
<property name="selectOptions" ref="selectOptions" />
|
||||
|
@ -282,10 +288,14 @@
|
|||
|
||||
<bean id ="modelDataConverter" class="org.datagear.web.convert.ModelDataConverter">
|
||||
<property name="conversionService" ref="conversionService" />
|
||||
<property name="variableExpressionResolver" ref="variableExpressionResolver" />
|
||||
<property name="sqlExpressionResolver" ref="sqlExpressionResolver" />
|
||||
</bean>
|
||||
|
||||
<bean id ="classDataConverter" class="org.datagear.web.convert.ClassDataConverter">
|
||||
<property name="conversionService" ref="conversionService" />
|
||||
<property name="variableExpressionResolver" ref="variableExpressionResolver" />
|
||||
<property name="sqlExpressionResolver" ref="sqlExpressionResolver" />
|
||||
</bean>
|
||||
|
||||
<bean id="fileSerializer" class="org.datagear.web.json.fastjson.FileSerializer">
|
||||
|
|
|
@ -77,7 +77,8 @@ error.RecordNotFoundOrPermissionDeniedException=\u8BB0\u5F55\u6216\u8BB8\u5DF2\u
|
|||
error.SchemaNotFoundException=\u672A\u627E\u5230\u6B64\u6570\u636E\u5E93
|
||||
error.IllegalSourceValueException=\u6570\u636E\u8F6C\u6362\u51FA\u9519\uFF1A\u65E0\u6CD5\u5C06[{0}]\u8F6C\u6362\u4E3A[{1}]
|
||||
error.FileNotFoundException=\u672A\u627E\u5230\u6587\u4EF6[{0}]
|
||||
error.SqlExpressionErrorException=\u6267\u884CSQL\u8868\u8FBE\u5F0F\u51FA\u9519
|
||||
error.VariableExpressionErrorException=\u8868\u8FBE\u5F0F\u683C\u5F0F\u6709\u8BEF\uFF1A<div class='content-value-sub'>{0}</div>
|
||||
error.SqlExpressionErrorException=\u6267\u884CSQL\u8BED\u53E5\u51FA\u9519\uFF1A<div class='content-value-sub'>{0}</div>
|
||||
error.UnsupportedDialectException=\u6570\u636E\u5E93\u8BBF\u95EE\u51FA\u9519\uFF0C\u7CFB\u7EDF\u4E0D\u652F\u6301\u8BBF\u95EE\u6B64\u6570\u636E\u5E93
|
||||
error.PersistenceException=\u6570\u636E\u5E93\u8BBF\u95EE\u51FA\u9519
|
||||
error.NotUniqueRecordException=\u65E0\u6CD5\u552F\u4E00\u786E\u5B9A\u8BB0\u5F55\uFF0C\u6570\u636E\u6709\u91CD\u590D
|
||||
|
|
|
@ -366,7 +366,8 @@
|
|||
*/
|
||||
tipSuccess : function(content, delayMs)
|
||||
{
|
||||
content = "<span class='ui-icon ui-icon-circle-check' style='margin-right:0.3em;'></span>" + content;
|
||||
content = "<span class='tooltip-icon ui-icon ui-icon-circle-check'></span>"
|
||||
+"<div class='content-value'>" + content +"</div>";
|
||||
return $._tip("ui-state-default", content, (delayMs || 2000));
|
||||
},
|
||||
|
||||
|
@ -375,8 +376,9 @@
|
|||
*/
|
||||
tipError : function(content, delayMs)
|
||||
{
|
||||
content = "<span class='ui-icon ui-icon-alert' style='margin-right:0.3em;'></span>" + content;
|
||||
return $._tip("ui-state-error", content, (delayMs || 5000));
|
||||
content = "<span class='tooltip-icon ui-icon ui-icon-alert'></span>"
|
||||
+"<div class='content-value'>" + content +"</div>";
|
||||
return $._tip("ui-state-error", content, (delayMs || 3500));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -384,8 +386,9 @@
|
|||
*/
|
||||
tipInfo : function(content, delayMs)
|
||||
{
|
||||
content = "<span class='ui-icon ui-icon-info' style='margin-right:0.3em;'></span>" + content;
|
||||
return $._tip("ui-state-highlight", content, (delayMs || 5000));
|
||||
content = "<span class='tooltip-icon ui-icon ui-icon-info'></span>"
|
||||
+"<div class='content-value'>" + content +"</div>";
|
||||
return $._tip("ui-state-highlight", content, (delayMs || 3500));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -412,7 +415,7 @@
|
|||
*/
|
||||
_tip : function(tooltipClass, content, delayMs)
|
||||
{
|
||||
content = "<div style='padding-left:0.5em;padding-right:0.5em; white-space: nowrap;'>" + content +"</div>";
|
||||
content = "<div class='content'>" + content +"</div>";
|
||||
|
||||
var tooltip = $(".global-tooltip", document.body);
|
||||
if(tooltip.length > 0)
|
||||
|
|
|
@ -336,9 +336,26 @@ table.dataTable tbody tr.selected .checkbox .ui-icon{
|
|||
margin-left: 0.3em;
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
.ui-tooltip .ui-tooltip-content .tooltip-icon{
|
||||
margin-right: 0.41em;
|
||||
}
|
||||
.ui-tooltip .ui-tooltip-content .error-detail-icon{
|
||||
cursor: pointer;
|
||||
}
|
||||
.ui-tooltip .ui-tooltip-content .content{
|
||||
padding-left:0.5em;
|
||||
padding-right:0.5em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.ui-tooltip .ui-tooltip-content .content .content-value{
|
||||
display: inline-block;
|
||||
}
|
||||
.ui-tooltip .ui-tooltip-content .content .content-value .content-value-sub{
|
||||
display: inline-block;
|
||||
max-width: 41em;
|
||||
vertical-align: bottom;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/*错误消息对话框*/
|
||||
.error-dialog{
|
||||
|
|
Loading…
Reference in New Issue