Search in sources :

Example 1 with OneToMany

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;
}
Also used : Field(java.lang.reflect.Field) OneToOne(org.sagacity.sqltoy.config.annotation.OneToOne) TableCascadeModel(org.sagacity.sqltoy.config.model.TableCascadeModel) OneToMany(org.sagacity.sqltoy.config.annotation.OneToMany)

Example 2 with OneToMany

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");
    }
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) OneToOne(org.sagacity.sqltoy.config.annotation.OneToOne) TableCascadeModel(org.sagacity.sqltoy.config.model.TableCascadeModel) OneToMany(org.sagacity.sqltoy.config.annotation.OneToMany)

Example 3 with OneToMany

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);
    }
}
Also used : OneToMany(org.sagacity.sqltoy.config.annotation.OneToMany) OneToManyModel(org.sagacity.sqltoy.config.model.OneToManyModel)

Aggregations

OneToMany (org.sagacity.sqltoy.config.annotation.OneToMany)3 OneToOne (org.sagacity.sqltoy.config.annotation.OneToOne)2 TableCascadeModel (org.sagacity.sqltoy.config.model.TableCascadeModel)2 Field (java.lang.reflect.Field)1 EntityMeta (org.sagacity.sqltoy.config.model.EntityMeta)1 OneToManyModel (org.sagacity.sqltoy.config.model.OneToManyModel)1