use of org.sagacity.sqltoy.config.annotation.OneToMany in project sagacity-sqltoy by chenrenfei.
the class BeanUtil method getCascadeModels.
/**
* @TODO 获取类的级联关系
* @param entityClass
* @return
*/
public static List<TableCascadeModel> getCascadeModels(Class entityClass) {
String className = entityClass.getName();
List<TableCascadeModel> result = cascadeModels.get(className);
if (result == null) {
result = new ArrayList<TableCascadeModel>();
Field[] cascadeFields = parseCascadeFields(entityClass);
for (Field field : cascadeFields) {
TableCascadeModel cascadeModel = new TableCascadeModel();
cascadeModel.setProperty(field.getName());
cascadeModel.setMappedType((Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]);
OneToMany oneToMany = field.getAnnotation(OneToMany.class);
OneToOne oneToOne = field.getAnnotation(OneToOne.class);
if (oneToMany != null) {
cascadeModel.setCascadeType(1);
cascadeModel.setFields(oneToMany.fields());
cascadeModel.setMappedFields(oneToMany.mappedFields());
} else {
cascadeModel.setCascadeType(2);
cascadeModel.setFields(oneToOne.fields());
cascadeModel.setMappedFields(oneToOne.mappedFields());
}
result.add(cascadeModel);
}
cascadeModels.put(className, result);
}
return result;
}
use of org.sagacity.sqltoy.config.annotation.OneToMany in project sagacity-sqltoy by chenrenfei.
the class EntityManager method parseCascade.
/**
* @todo 解析主键关联的子表信息配置(外键关联)
* @param sqlToyContext
* @param entityMeta
* @param entity
* @param field
* @param idList
*/
private void parseCascade(SqlToyContext sqlToyContext, EntityMeta entityMeta, Entity entity, Field field, List<String> idList) {
// 主表关联多子表记录
OneToMany oneToMany = field.getAnnotation(OneToMany.class);
OneToOne oneToOne = field.getAnnotation(OneToOne.class);
if (oneToMany == null && oneToOne == null) {
return;
}
TableCascadeModel cascadeModel = new TableCascadeModel();
String[] fields;
String[] mappedFields;
String load = null;
String orderBy = null;
String update = null;
// oneToMany
if (oneToMany != null) {
fields = oneToMany.fields();
mappedFields = oneToMany.mappedFields();
cascadeModel.setCascadeType(1);
cascadeModel.setMappedType((Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]);
load = oneToMany.load();
orderBy = oneToMany.orderBy();
update = oneToMany.update();
// 是否交由sqltoy进行级联删除,数据库本身存在自动级联机制
cascadeModel.setDelete(oneToMany.delete());
} else {
fields = oneToOne.fields();
mappedFields = oneToOne.mappedFields();
cascadeModel.setCascadeType(2);
cascadeModel.setMappedType(field.getType());
load = oneToOne.load();
update = oneToOne.update();
cascadeModel.setDelete(oneToOne.delete());
}
// 获取子表的信息(存在递归调用)
EntityMeta subTableMeta = getEntityMeta(sqlToyContext, cascadeModel.getMappedType());
if ((fields == null || fields.length == 0) && idList.size() == 1) {
fields = entityMeta.getIdArray();
}
if (fields == null || fields.length != mappedFields.length) {
throw new IllegalArgumentException(StringUtil.fillArgs("主表:{}的fields 跟子表:{} mappedFields 长度不一致,请检查!", entityMeta.getTableName(), subTableMeta.getTableName()));
}
String[] mappedColumns = new String[fields.length];
// 剔除下划线,避免手工维护时将属性名称写成数据库字段名称
fields = StringUtil.humpFieldNames(fields);
mappedFields = StringUtil.humpFieldNames(mappedFields);
// 主表字段名称
for (int i = 0; i < fields.length; i++) {
// 检查属性名称配置是否正确
if (entityMeta.getFieldMeta(fields[i]) == null) {
throw new IllegalArgumentException(StringUtil.fillArgs("表级联配置对应主表:{}的field属性:{} 并不存在,请检查!", entityMeta.getTableName(), fields[i]));
}
if (subTableMeta.getFieldMeta(mappedFields[i]) == null) {
throw new IllegalArgumentException(StringUtil.fillArgs("表级联配置对应子表:{}的field属性:{} 并不存在,请检查!", subTableMeta.getTableName(), mappedFields[i]));
}
// 提取子表属性对应的数据库字段名称,并进行关键词处理
mappedColumns[i] = ReservedWordsUtil.convertWord(subTableMeta.getColumnName(mappedFields[i]), null);
}
cascadeModel.setFields(fields);
cascadeModel.setMappedColumns(mappedColumns);
cascadeModel.setMappedFields(mappedFields);
// 子表的schema.table
String subSchemaTable = subTableMeta.getSchemaTable(null, null);
cascadeModel.setMappedTable(subSchemaTable);
cascadeModel.setProperty(field.getName());
// 子表外键查询条件
String subWhereSql = " where ";
// 级联删除,自动组装sql不允许外部修改,所以用?作为条件,顺序在对象加载时约定
String subDeleteSql = "delete from ".concat(subSchemaTable).concat(" where ");
for (int i = 0; i < fields.length; i++) {
if (i > 0) {
subWhereSql = subWhereSql.concat(" and ");
subDeleteSql = subDeleteSql.concat(" and ");
}
subWhereSql = subWhereSql.concat(mappedColumns[i]).concat("=:").concat(mappedFields[i]);
subDeleteSql = subDeleteSql.concat(mappedColumns[i]).concat("=?");
}
cascadeModel.setLoadSubTableSql(subTableMeta.getLoadAllSql().concat(subWhereSql));
cascadeModel.setDeleteSubTableSql(subDeleteSql);
boolean matchedWhere = false;
// 自定义load sql
if (StringUtil.isNotBlank(load)) {
String loadLow = load.toLowerCase();
// 是否是:xxx形式的引入主键条件(原则上不允许这么操作)
boolean isNamedSql = SqlConfigParseUtils.isNamedQuery(load);
if (isNamedSql && !StringUtil.matches(loadLow, "(\\>|\\<)|(\\=)|(\\<\\>)|(\\>\\=|\\<\\=)")) {
// 自定义加载完整sql
if (!loadLow.equals("default") && !loadLow.equals("true")) {
cascadeModel.setLoadSubTableSql(load);
}
} else {
String loadSql = SqlUtil.convertFieldsToColumns(subTableMeta, load);
matchedWhere = StringUtil.matches(loadLow, "\\s+where\\s+");
if (matchedWhere) {
cascadeModel.setLoadSubTableSql(loadSql);
} else {
cascadeModel.setLoadSubTableSql(subTableMeta.getLoadAllSql().concat(subWhereSql).concat(" and ").concat(loadSql));
cascadeModel.setLoadExtCondition(loadSql);
}
}
}
// update 2020-11-20 增加子表级联order by
if (StringUtil.isNotBlank(orderBy)) {
// 对属性名称进行替换,替换为实际表字段名称
orderBy = SqlUtil.convertFieldsToColumns(subTableMeta, orderBy);
cascadeModel.setOrderBy(orderBy);
cascadeModel.setLoadSubTableSql(cascadeModel.getLoadSubTableSql().concat(" order by ").concat(orderBy));
}
// 深度级联修改
if (StringUtil.isNotBlank(update)) {
String updateLow = update;
// 表示先删除子表
if (updateLow.equals("delete")) {
cascadeModel.setCascadeUpdateSql("delete from ".concat(subSchemaTable).concat(subWhereSql));
} else {
// 修改数据(如设置记录状态为失效)
matchedWhere = StringUtil.matches(updateLow, "\\s+where\\s+");
cascadeModel.setCascadeUpdateSql("update ".concat(subSchemaTable).concat(" set ").concat(update).concat(matchedWhere ? "" : subWhereSql));
}
}
// 是否完成了覆盖
boolean isRepeat = entityMeta.addCascade(cascadeModel);
if (isRepeat) {
logger.warn("表:{} 级联操作子表:{} 出现重复关联,后续:{}关联类型覆盖前面的关联", entityMeta.getTableName(), subTableMeta.getTableName(), (cascadeModel.getCascadeType() == 1) ? "oneToMany" : "oneToOne");
}
}
use of org.sagacity.sqltoy.config.annotation.OneToMany 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