use of org.sagacity.sqltoy.config.model.OneToManyModel in project sagacity-sqltoy by chenrenfei.
the class SapIQDialectUtils method save.
/**
* @todo 保存对象(sybase iq支持sequence)
* @param sqlToyContext
* @param entity
* @param openIdentity
* @param conn
* @param tableName
* @return
* @throws Exception
*/
public static Object save(SqlToyContext sqlToyContext, Serializable entity, boolean openIdentity, final Connection conn, String tableName) throws Exception {
final EntityMeta entityMeta = sqlToyContext.getEntityMeta(entity.getClass());
final boolean isIdentity = entityMeta.getIdStrategy() != null && entityMeta.getIdStrategy().equals(PKStrategy.IDENTITY);
final boolean isSequence = entityMeta.getIdStrategy() != null && entityMeta.getIdStrategy().equals(PKStrategy.SEQUENCE);
String insertSql = DialectUtils.generateInsertSql(DBType.SYBASE_IQ, entityMeta, entityMeta.getIdStrategy(), null, "@mySeqVariable", false, tableName);
if (isSequence)
insertSql = "set nocount on DECLARE @mySeqVariable decimal(20) select @mySeqVariable=" + entityMeta.getSequence() + ".NEXTVAL " + insertSql + " select @mySeqVariable ";
// 无主键,或多主键且非identity、sequence模式
boolean noPK = (entityMeta.getIdArray() == null);
int pkIndex = entityMeta.getIdIndex();
Object[] fullParamValues = BeanUtil.reflectBeanToAry(entity, (isIdentity || isSequence) ? entityMeta.getRejectIdFieldArray() : entityMeta.getFieldsArray(), null, null);
boolean needUpdatePk = false;
// 是否存在业务ID
boolean hasBizId = (entityMeta.getBusinessIdGenerator() == null) ? false : true;
int bizIdColIndex = hasBizId ? entityMeta.getFieldIndex(entityMeta.getBusinessIdField()) : 0;
// 标识符
String signature = entityMeta.getBizIdSignature();
Integer relatedColumn = entityMeta.getBizIdRelatedColIndex();
// 主键采用assign方式赋予,则调用generator产生id并赋予其值
if (entityMeta.getIdStrategy() != null && null != entityMeta.getIdGenerator()) {
int idLength = entityMeta.getIdLength();
int bizIdLength = entityMeta.getBizIdLength();
Object relatedColValue = null;
int businessIdType = hasBizId ? entityMeta.getColumnType(entityMeta.getBusinessIdField()) : 0;
if (relatedColumn != null) {
relatedColValue = fullParamValues[relatedColumn];
}
if (StringUtil.isBlank(fullParamValues[pkIndex])) {
// id通过generator机制产生,设置generator产生的值
fullParamValues[pkIndex] = entityMeta.getIdGenerator().getId(entityMeta.getSchemaTable(), signature, relatedColValue, null, entityMeta.getIdType(), idLength);
needUpdatePk = true;
}
if (hasBizId && StringUtil.isBlank(fullParamValues[bizIdColIndex])) {
fullParamValues[bizIdColIndex] = entityMeta.getBusinessIdGenerator().getId(entityMeta.getTableName(), signature, relatedColValue, null, businessIdType, bizIdLength);
// 回写业务主键值
BeanUtils.setProperty(entity, entityMeta.getBusinessIdField(), fullParamValues[bizIdColIndex]);
}
}
final Object[] paramValues = fullParamValues;
final Integer[] paramsType = entityMeta.getFieldsTypeArray();
if (isIdentity)
insertSql = insertSql + " select @@IDENTITY ";
if (sqlToyContext.isDebug())
out.println(insertSql);
final String realInsertSql = insertSql;
PreparedStatement pst = null;
Object result = SqlUtil.preparedStatementProcess(null, pst, null, new PreparedStatementResultHandler() {
public void execute(Object obj, PreparedStatement pst, ResultSet rs) throws SQLException, IOException {
pst = conn.prepareStatement(realInsertSql);
// 存在默认值
if (entityMeta.isHasDefaultValue())
SqlUtilsExt.setParamsValue(conn, pst, paramValues, entityMeta);
else
SqlUtil.setParamsValue(conn, pst, paramValues, paramsType, 0);
ResultSet keyResult = null;
if (isSequence || isIdentity)
keyResult = pst.executeQuery();
else
pst.execute();
if (isSequence || isIdentity) {
while (keyResult.next()) this.setResult(keyResult.getObject(1));
}
}
});
// 无主键直接返回null
if (noPK)
return null;
else {
if (result == null)
result = fullParamValues[pkIndex];
// 回置到entity 主键值
if (needUpdatePk || isIdentity || isSequence) {
BeanUtils.setProperty(entity, entityMeta.getIdArray()[0], result);
}
// 判断是否有子表级联保存
if (!entityMeta.getOneToManys().isEmpty()) {
List subTableData;
final Object[] idValues = BeanUtil.reflectBeanToAry(entity, entityMeta.getIdArray(), null, null);
for (OneToManyModel oneToMany : entityMeta.getOneToManys()) {
final String[] mappedFields = oneToMany.getMappedFields();
subTableData = (List) PropertyUtils.getProperty(entity, oneToMany.getProperty());
if (subTableData != null && !subTableData.isEmpty()) {
saveAll(sqlToyContext, subTableData, sqlToyContext.getBatchSize(), new ReflectPropertyHandler() {
public void process() {
for (int i = 0; i < mappedFields.length; i++) {
this.setValue(mappedFields[i], idValues[i]);
}
}
}, openIdentity, conn, null);
}
}
}
return result;
}
}
use of org.sagacity.sqltoy.config.model.OneToManyModel in project sagacity-sqltoy by chenrenfei.
the class DialectUtils method update.
/**
* @todo 单个对象修改,包含接连修改
* @param sqlToyContext
* @param entity
* @param nullFunction
* @param forceUpdateFields
* @param cascade
* @param generateSqlHandler
* @param forceCascadeClasses
* @param subTableForceUpdateProps
* @param conn
* @param tableName
* @throws Exception
*/
public static Long update(SqlToyContext sqlToyContext, Serializable entity, String nullFunction, String[] forceUpdateFields, final boolean cascade, final GenerateSqlHandler generateSqlHandler, final Class[] forceCascadeClasses, final HashMap<Class, String[]> subTableForceUpdateProps, Connection conn, String tableName) throws Exception {
EntityMeta entityMeta = sqlToyContext.getEntityMeta(entity.getClass());
Long updateCnt = update(sqlToyContext, entity, entityMeta, nullFunction, forceUpdateFields, conn, tableName);
// 级联保存
if (cascade && !entityMeta.getOneToManys().isEmpty()) {
HashMap<Type, String> typeMap = new HashMap<Type, String>();
// 即使子对象数据是null,也强制进行级联修改(null表示删除子表数据)
if (forceCascadeClasses != null) {
for (Type type : forceCascadeClasses) {
typeMap.put(type, "");
}
}
// 级联子表数据
List subTableData;
final Object[] IdValues = BeanUtil.reflectBeanToAry(entity, entityMeta.getIdArray(), null, null);
String[] forceUpdateProps = null;
EntityMeta subTableEntityMeta;
// 对子表进行级联处理
for (OneToManyModel oneToMany : entityMeta.getOneToManys()) {
subTableEntityMeta = sqlToyContext.getEntityMeta(oneToMany.getMappedType());
forceUpdateProps = (subTableForceUpdateProps == null) ? null : subTableForceUpdateProps.get(oneToMany.getMappedType());
subTableData = (List) BeanUtil.invokeMethod(entity, "get".concat(StringUtil.firstToUpperCase(oneToMany.getProperty())), null);
final String[] mappedFields = oneToMany.getMappedFields();
/**
* 针对子表存量数据,调用级联修改的语句,分delete 和update两种操作 1、删除存量数据;2、设置存量数据状态为停用
*/
if (oneToMany.getCascadeUpdateSql() != null && ((subTableData != null && !subTableData.isEmpty()) || typeMap.containsKey(oneToMany.getMappedType()))) {
// 根据quickvo配置文件针对cascade中update-cascade配置组织具体操作sql
SqlToyResult sqlToyResult = SqlConfigParseUtils.processSql(oneToMany.getCascadeUpdateSql(), mappedFields, IdValues);
executeSql(sqlToyResult.getSql(), sqlToyResult.getParamsValue(), null, conn, null);
}
// 子表数据不为空,采取saveOrUpdateAll操作
if (subTableData != null && !subTableData.isEmpty()) {
saveOrUpdateAll(sqlToyContext, subTableData, sqlToyContext.getBatchSize(), subTableEntityMeta, forceUpdateProps, generateSqlHandler, // 设置关联外键字段的属性值(来自主表的主键)
new ReflectPropertyHandler() {
public void process() {
for (int i = 0; i < mappedFields.length; i++) {
this.setValue(mappedFields[i], IdValues[i]);
}
}
}, conn, null);
}
}
}
return updateCnt;
}
use of org.sagacity.sqltoy.config.model.OneToManyModel in project sagacity-sqltoy by chenrenfei.
the class SybaseIQDialect method update.
/*
* (non-Javadoc)
*
* @see org.sagacity.sqltoy.dialect.Dialect#update(org.sagacity.sqltoy.
* SqlToyContext , java.io.Serializable, java.lang.String[],
* java.sql.Connection)
*/
@Override
public Long update(SqlToyContext sqlToyContext, Serializable entity, String[] forceUpdateFields, final boolean cascade, final Class[] emptyCascadeClasses, final HashMap<Class, String[]> subTableForceUpdateProps, Connection conn, final String tableName) throws Exception {
EntityMeta entityMeta = sqlToyContext.getEntityMeta(entity.getClass());
Long updateCount = DialectUtils.update(sqlToyContext, entity, entityMeta, NVL_FUNCTION, forceUpdateFields, conn, tableName);
// 级联保存
if (cascade && null != entityMeta.getOneToManys() && !entityMeta.getOneToManys().isEmpty()) {
HashMap<Type, String> typeMap = new HashMap<Type, String>();
if (emptyCascadeClasses != null)
for (Type type : emptyCascadeClasses) {
typeMap.put(type, "");
}
// 级联子表数据
List subTableData;
final Object[] IdValues = BeanUtil.reflectBeanToAry(entity, entityMeta.getIdArray(), null, null);
String[] forceUpdateProps = null;
for (OneToManyModel oneToMany : entityMeta.getOneToManys()) {
forceUpdateProps = (subTableForceUpdateProps == null) ? null : subTableForceUpdateProps.get(oneToMany.getMappedType());
subTableData = (List) BeanUtil.invokeMethod(entity, "get".concat(StringUtil.firstToUpperCase(oneToMany.getProperty())), null);
final String[] mappedFields = oneToMany.getMappedFields();
/**
* 针对子表存量数据,调用级联修改的语句,分delete 和update两种操作 1、删除存量数据;2、设置存量数据状态为停用
*/
if (oneToMany.getCascadeUpdateSql() != null && ((subTableData != null && !subTableData.isEmpty()) || typeMap.containsKey(oneToMany.getMappedType()))) {
SqlToyResult sqlToyResult = SqlConfigParseUtils.processSql(oneToMany.getCascadeUpdateSql(), mappedFields, IdValues);
DialectUtils.executeSql(sqlToyResult.getSql(), sqlToyResult.getParamsValue(), null, conn, null);
}
// 子表数据不为空,采取saveOrUpdateAll操作
if (subTableData != null && !subTableData.isEmpty()) {
saveOrUpdateAll(sqlToyContext, subTableData, sqlToyContext.getBatchSize(), // 设置关联外键字段的属性值(来自主表的主键)
new ReflectPropertyHandler() {
public void process() {
for (int i = 0; i < mappedFields.length; i++) {
this.setValue(mappedFields[i], IdValues[i]);
}
}
}, forceUpdateProps, conn, null, null);
}
}
}
return updateCount;
}
use of org.sagacity.sqltoy.config.model.OneToManyModel in project sagacity-sqltoy by chenrenfei.
the class DialectUtils method loadAll.
/**
* @todo 提供统一的loadAll处理机制
* @param sqlToyContext
* @param sql
* @param entities
* @param cascadeTypes
* @param conn
* @return
* @throws Exception
*/
public static List<?> loadAll(final SqlToyContext sqlToyContext, String sql, List<?> entities, List<Class> cascadeTypes, Connection conn) throws Exception {
if (entities == null || entities.isEmpty())
return entities;
Class entityClass = entities.get(0).getClass();
EntityMeta entityMeta = sqlToyContext.getEntityMeta(entityClass);
// 没有主键不能进行load相关的查询
if (entityMeta.getIdArray() == null) {
throw new Exception("表:" + entityMeta.getSchemaTable() + " 没有主键,不符合load或loadAll规则,请检查表设计是否合理!");
}
// 主键值
List pkValues = BeanUtil.reflectBeansToList(entities, entityMeta.getIdArray());
int idSize = entityMeta.getIdArray().length;
List[] idValues = new List[idSize];
// 构造内部的list
for (int i = 0; i < idSize; i++) {
idValues[i] = new ArrayList();
}
List rowList;
// 检查主键值,主键值必须不为null
Object value;
for (int i = 0, n = pkValues.size(); i < n; i++) {
rowList = (List) pkValues.get(i);
for (int j = 0; j < idSize; j++) {
value = rowList.get(j);
if (null == value)
throw new Exception("loadAll method must assign value for pk,row:" + i + " pk field:" + entityMeta.getIdArray()[j]);
if (!idValues[j].contains(value)) {
idValues[j].add(value);
}
}
}
SqlToyResult sqlToyResult = SqlConfigParseUtils.processSql(sql, entityMeta.getIdArray(), idValues);
SqlExecuteStat.showSql(sqlToyResult.getSql(), sqlToyResult.getParamsValue());
List<?> entitySet = SqlUtil.findByJdbcQuery(sqlToyResult.getSql(), sqlToyResult.getParamsValue(), entityClass, null, conn);
// 存在主表对应子表
if (null != cascadeTypes && !cascadeTypes.isEmpty() && !entityMeta.getOneToManys().isEmpty()) {
StringBuilder subTableSql = new StringBuilder();
List items;
SqlToyResult subToyResult;
for (OneToManyModel oneToMany : entityMeta.getOneToManys()) {
if (cascadeTypes.contains(oneToMany.getMappedType())) {
// 清空buffer
subTableSql.delete(0, subTableSql.length());
subTableSql.append("select * from ").append(oneToMany.getMappedTable()).append(" where ");
for (int i = 0; i < idSize; i++) {
if (i > 0)
subTableSql.append(" and ");
subTableSql.append(oneToMany.getMappedColumns()[i]);
subTableSql.append(" in (:" + entityMeta.getIdArray()[i] + ") ");
}
subToyResult = SqlConfigParseUtils.processSql(subTableSql.toString(), entityMeta.getIdArray(), idValues);
SqlExecuteStat.showSql(subToyResult.getSql(), subToyResult.getParamsValue());
items = SqlUtil.findByJdbcQuery(subToyResult.getSql(), subToyResult.getParamsValue(), oneToMany.getMappedType(), null, conn);
// 调用vo中mapping方法,将子表对象规整到主表对象的oneToMany集合中
BeanUtil.invokeMethod(entities.get(0), "mapping" + StringUtil.firstToUpperCase(oneToMany.getProperty()), new Object[] { entitySet, items });
}
}
}
return entitySet;
}
use of org.sagacity.sqltoy.config.model.OneToManyModel in project sagacity-sqltoy by chenrenfei.
the class EntityManager method parseOneToMany.
/**
* @todo 解析主键关联的子表信息配置(外键关联)
* @param entityMeta
* @param entity
* @param field
* @param idList
* @param idsIndexMap
*/
private void parseOneToMany(EntityMeta entityMeta, Entity entity, Field field, List<String> idList, HashMap<String, Integer> idsIndexMap) {
// 主键字段数量
int idSize = idList.size();
int idIndex = 0;
// 主表关联多子表记录
OneToMany oneToMany = field.getAnnotation(OneToMany.class);
if (oneToMany != null) {
if (idSize != oneToMany.mappedColumns().length)
logger.error("主表:{}的主键字段数量:{}与子表:{}的外键关联字段数量:{}不等,请检查!", entityMeta.getTableName(), idSize, oneToMany.mappedTable(), oneToMany.mappedColumns().length);
OneToManyModel oneToManyModel = new OneToManyModel();
String[] mappedColumns = new String[idSize];
String[] mappedFields = new String[idSize];
// 按照主键顺序排列外键顺序
for (int i = 0; i < idSize; i++) {
idIndex = idsIndexMap.get(idList.get(i));
mappedColumns[i] = oneToMany.mappedColumns()[idIndex];
mappedFields[i] = oneToMany.mappedFields()[idIndex];
}
oneToManyModel.setMappedColumns(mappedColumns);
oneToManyModel.setMappedFields(mappedFields);
// 子表的schema.table
String subSchemaTable = (StringUtil.isBlank(entity.schema()) ? "" : (entity.schema().concat("."))).concat(oneToMany.mappedTable());
oneToManyModel.setMappedTable(subSchemaTable);
oneToManyModel.setProperty(field.getName());
oneToManyModel.setMappedType((Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]);
// 是否交由sqltoy进行级联删除,数据库本身存在自动级联机制
oneToManyModel.setDelete(oneToMany.delete());
// 子表外键查询条件
String subWhereSql = " where ";
for (int i = 0; i < idSize; i++) {
if (i > 0)
subWhereSql = subWhereSql.concat(" and ");
subWhereSql = subWhereSql.concat(mappedColumns[i]).concat("=:").concat(mappedFields[i]);
}
boolean matchedWhere = false;
// 默认load为true,由程序员通过程序指定哪些子表是否需要加载
oneToManyModel.setLoad(true);
oneToManyModel.setLoadSubTableSql("select * from ".concat(subSchemaTable).concat(subWhereSql));
// 自动加载
if (StringUtil.isNotBlank(oneToMany.load())) {
// 是否是:xxx形式的参数条件
boolean isNamedSql = SqlConfigParseUtils.isNamedQuery(oneToMany.load());
if (isNamedSql && !StringUtil.matches(oneToMany.load(), "(\\>|\\<)|(\\=)|(\\<\\>)|(\\>\\=|\\<\\=)")) {
// 自定义加载sql
if (!oneToMany.load().equalsIgnoreCase("default") && !oneToMany.load().equalsIgnoreCase("true"))
oneToManyModel.setLoadSubTableSql(oneToMany.load());
} else {
matchedWhere = StringUtil.matches(oneToMany.load().toLowerCase(), "\\s+where\\s+");
if (matchedWhere)
oneToManyModel.setLoadSubTableSql(oneToMany.load());
else
oneToManyModel.setLoadSubTableSql("select * from ".concat(subSchemaTable).concat(subWhereSql).concat(" and ").concat(oneToMany.load()));
}
}
// 级联删除,自动组装sql不允许外部修改,所以用?作为条件,顺序在对象加载时约定
String subDeleteSql = "delete from ".concat(subSchemaTable).concat(" where ");
for (int i = 0; i < idList.size(); i++) {
if (i > 0)
subDeleteSql = subDeleteSql.concat(" and ");
subDeleteSql = subDeleteSql.concat(mappedColumns[i]).concat("=?");
}
oneToManyModel.setDeleteSubTableSql(subDeleteSql);
// 深度级联修改
if (StringUtil.isNotBlank(oneToMany.update())) {
// 表示先删除子表
if (oneToMany.update().equalsIgnoreCase("delete"))
oneToManyModel.setCascadeUpdateSql("delete from ".concat(subSchemaTable).concat(subWhereSql));
else {
// 修改数据(如设置记录状态为失效)
matchedWhere = StringUtil.matches(oneToMany.update().toLowerCase(), "\\s+where\\s+");
oneToManyModel.setCascadeUpdateSql("update ".concat(subSchemaTable).concat(" set ").concat(oneToMany.update()).concat(matchedWhere ? "" : subWhereSql));
}
}
entityMeta.addOneToMany(oneToManyModel);
}
}
Aggregations