Search in sources :

Example 6 with OneToManyModel

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;
    }
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) SQLException(java.sql.SQLException) PreparedStatementResultHandler(org.sagacity.sqltoy.callback.PreparedStatementResultHandler) PreparedStatement(java.sql.PreparedStatement) IOException(java.io.IOException) ResultSet(java.sql.ResultSet) ArrayList(java.util.ArrayList) List(java.util.List) ReflectPropertyHandler(org.sagacity.sqltoy.callback.ReflectPropertyHandler) OneToManyModel(org.sagacity.sqltoy.config.model.OneToManyModel)

Example 7 with OneToManyModel

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;
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) HashMap(java.util.HashMap) SqlToyResult(org.sagacity.sqltoy.config.model.SqlToyResult) ReturnPkType(org.sagacity.sqltoy.dialect.model.ReturnPkType) Type(java.lang.reflect.Type) List(java.util.List) ArrayList(java.util.ArrayList) ReflectPropertyHandler(org.sagacity.sqltoy.callback.ReflectPropertyHandler) OneToManyModel(org.sagacity.sqltoy.config.model.OneToManyModel)

Example 8 with OneToManyModel

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;
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) HashMap(java.util.HashMap) SqlToyResult(org.sagacity.sqltoy.config.model.SqlToyResult) SqlType(org.sagacity.sqltoy.config.model.SqlType) DBType(org.sagacity.sqltoy.utils.DataSourceUtils.DBType) Type(java.lang.reflect.Type) ArrayList(java.util.ArrayList) List(java.util.List) ReflectPropertyHandler(org.sagacity.sqltoy.callback.ReflectPropertyHandler) OneToManyModel(org.sagacity.sqltoy.config.model.OneToManyModel)

Example 9 with OneToManyModel

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;
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) SQLException(java.sql.SQLException) IOException(java.io.IOException) OneToManyModel(org.sagacity.sqltoy.config.model.OneToManyModel) SqlToyResult(org.sagacity.sqltoy.config.model.SqlToyResult)

Example 10 with OneToManyModel

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

Aggregations

OneToManyModel (org.sagacity.sqltoy.config.model.OneToManyModel)10 EntityMeta (org.sagacity.sqltoy.config.model.EntityMeta)8 IOException (java.io.IOException)7 SQLException (java.sql.SQLException)7 ArrayList (java.util.ArrayList)7 List (java.util.List)7 ReflectPropertyHandler (org.sagacity.sqltoy.callback.ReflectPropertyHandler)5 SqlToyResult (org.sagacity.sqltoy.config.model.SqlToyResult)4 PreparedStatement (java.sql.PreparedStatement)3 ResultSet (java.sql.ResultSet)3 PreparedStatementResultHandler (org.sagacity.sqltoy.callback.PreparedStatementResultHandler)3 Type (java.lang.reflect.Type)2 HashMap (java.util.HashMap)2 Serializable (java.io.Serializable)1 OneToMany (org.sagacity.sqltoy.config.annotation.OneToMany)1 SqlType (org.sagacity.sqltoy.config.model.SqlType)1 GenerateSavePKStrategy (org.sagacity.sqltoy.dialect.handler.GenerateSavePKStrategy)1 ReturnPkType (org.sagacity.sqltoy.dialect.model.ReturnPkType)1 SavePKStrategy (org.sagacity.sqltoy.dialect.model.SavePKStrategy)1 QueryResult (org.sagacity.sqltoy.model.QueryResult)1