Search in sources :

Example 41 with EntityMeta

use of org.sagacity.sqltoy.config.model.EntityMeta in project sagacity-sqltoy by chenrenfei.

the class SqlToyDaoSupport method findEntityBase.

/**
 * @TODO 提供findEntity的基础实现,供对外接口包装,额外开放了resultClass的自定义功能
 * @param entityClass
 * @param page        如分页查询则需指定,非分页则传null
 * @param entityQuery
 * @param resultClass 指定返回结果类型
 * @param isCount
 * @return
 */
private Object findEntityBase(Class entityClass, Page page, EntityQuery entityQuery, Class resultClass, boolean isCount) {
    EntityMeta entityMeta = getEntityMeta(entityClass);
    EntityQueryExtend innerModel = entityQuery.getInnerModel();
    String translateFields = "";
    // 将缓存翻译对应的查询补充到select column 上,形成select keyColumn as viewColumn 模式
    if (!innerModel.translates.isEmpty()) {
        Iterator<Translate> iter = innerModel.translates.values().iterator();
        String keyColumn;
        TranslateExtend extend;
        while (iter.hasNext()) {
            extend = iter.next().getExtend();
            // 将java模式的字段名称转化为数据库字段名称
            keyColumn = entityMeta.getColumnName(extend.keyColumn);
            if (keyColumn == null) {
                keyColumn = extend.keyColumn;
            }
            // 保留字处理
            keyColumn = ReservedWordsUtil.convertWord(keyColumn, null);
            translateFields = translateFields.concat(",").concat(keyColumn).concat(" as ").concat(extend.column);
        }
    }
    // 将notSelect构造成select,形成统一处理机制
    String[] selectFieldAry = null;
    Set<String> notSelect = innerModel.notSelectFields;
    if (notSelect != null) {
        List<String> selectFields = new ArrayList<String>();
        for (String field : entityMeta.getFieldsArray()) {
            if (!notSelect.contains(field.toLowerCase())) {
                selectFields.add(field);
            }
        }
        if (selectFields.size() > 0) {
            selectFieldAry = new String[selectFields.size()];
            selectFields.toArray(selectFieldAry);
        }
    } else {
        selectFieldAry = innerModel.fields;
    }
    // 指定的查询字段
    String fields = "";
    if (selectFieldAry != null && selectFieldAry.length > 0) {
        int index = 0;
        String colName;
        HashSet<String> cols = new HashSet<String>();
        boolean notAllPureField = false;
        for (String field : selectFieldAry) {
            // 去除重复字段
            if (!cols.contains(field)) {
                colName = entityMeta.getColumnName(field);
                // 非表字段对应pojo的属性名称
                if (colName == null) {
                    colName = field;
                    // 非字段名称
                    if (!entityMeta.getColumnFieldMap().containsKey(colName.toLowerCase())) {
                        notAllPureField = true;
                    } else {
                        // 保留字处理
                        colName = ReservedWordsUtil.convertWord(colName, null);
                    }
                } else {
                    // 保留字处理
                    colName = ReservedWordsUtil.convertWord(colName, null);
                }
                if (index > 0) {
                    fields = fields.concat(",");
                }
                fields = fields.concat(colName);
                index++;
                cols.add(field);
            }
        }
        // select 字段中可能存在max(field)或field as xxx等非字段形式
        if (notAllPureField) {
            fields = SqlUtil.convertFieldsToColumns(entityMeta, fields);
        }
    } else {
        fields = entityMeta.getAllColumnNames();
    }
    String sql = "select ".concat((innerModel.distinct) ? " distinct " : "").concat(fields).concat(translateFields).concat(" from ").concat(entityMeta.getSchemaTable(null, null));
    // where条件
    String where = "";
    // 动态组织where 后面的条件语句,此功能并不建议使用,where 一般需要指定明确条件
    if (StringUtil.isBlank(innerModel.where)) {
        if (innerModel.values != null && innerModel.values.length > 0) {
            where = SqlUtil.wrapWhere(entityMeta);
        }
    } else {
        where = SqlUtil.convertFieldsToColumns(entityMeta, innerModel.where);
    }
    if (StringUtil.isNotBlank(where)) {
        sql = sql.concat(" where ").concat(where);
    }
    // 分组和having
    if (StringUtil.isNotBlank(innerModel.groupBy)) {
        sql = sql.concat(" group by ").concat(SqlUtil.convertFieldsToColumns(entityMeta, innerModel.groupBy));
        if (StringUtil.isNotBlank(innerModel.having)) {
            sql = sql.concat(" having ").concat(SqlUtil.convertFieldsToColumns(entityMeta, innerModel.having));
        }
    }
    // 处理order by 排序
    if (!innerModel.orderBy.isEmpty()) {
        sql = sql.concat(" order by ");
        Iterator<Entry<String, String>> iter = innerModel.orderBy.entrySet().iterator();
        Entry<String, String> entry;
        String columnName;
        int index = 0;
        while (iter.hasNext()) {
            entry = iter.next();
            columnName = entityMeta.getColumnName(entry.getKey());
            if (columnName == null) {
                columnName = entry.getKey();
            }
            // 保留字处理
            columnName = ReservedWordsUtil.convertWord(columnName, null);
            if (index > 0) {
                sql = sql.concat(",");
            }
            // entry.getValue() is order way,like: desc or " "
            sql = sql.concat(columnName).concat(entry.getValue());
            index++;
        }
    }
    QueryExecutor queryExecutor;
    Class resultType = (resultClass == null) ? entityClass : resultClass;
    // :named 模式(named模式参数值必须存在)
    if (SqlConfigParseUtils.hasNamedParam(where) && StringUtil.isBlank(innerModel.names)) {
        queryExecutor = new QueryExecutor(sql, (innerModel.values == null || innerModel.values.length == 0) ? null : (Serializable) innerModel.values[0]).resultType(resultType).dataSource(getDataSource(innerModel.dataSource)).fetchSize(innerModel.fetchSize).maxRows(innerModel.maxRows);
    } else {
        queryExecutor = new QueryExecutor(sql).names(innerModel.names).values(innerModel.values).resultType(resultType).dataSource(getDataSource(innerModel.dataSource)).fetchSize(innerModel.fetchSize).maxRows(innerModel.maxRows);
    }
    // 设置是否空白转null
    queryExecutor.getInnerModel().blankToNull = innerModel.blankToNull;
    // 设置额外的缓存翻译
    if (!innerModel.translates.isEmpty()) {
        queryExecutor.getInnerModel().translates.putAll(innerModel.translates);
    }
    // 设置额外的参数条件过滤
    if (!innerModel.paramFilters.isEmpty()) {
        queryExecutor.getInnerModel().paramFilters.addAll(innerModel.paramFilters);
    }
    // 设置安全脱敏
    if (!innerModel.secureMask.isEmpty()) {
        queryExecutor.getInnerModel().secureMask.putAll(innerModel.secureMask);
    }
    // 设置分页优化
    queryExecutor.getInnerModel().pageOptimize = innerModel.pageOptimize;
    SqlToyConfig sqlToyConfig = sqlToyContext.getSqlToyConfig(queryExecutor, SqlType.search, getDialect(queryExecutor.getInnerModel().dataSource));
    // 加密字段,查询时解密
    if (entityMeta.getSecureColumns() != null) {
        sqlToyConfig.setDecryptColumns(entityMeta.getSecureColumns());
    }
    // 分库分表策略
    setEntitySharding(queryExecutor, entityMeta);
    if (innerModel.dbSharding != null) {
        queryExecutor.getInnerModel().dbSharding = innerModel.dbSharding;
    }
    if (innerModel.tableSharding != null) {
        ShardingStrategyConfig shardingConfig = innerModel.tableSharding;
        // 补充表名称
        shardingConfig.setTables(new String[] { entityMeta.getTableName() });
        List<ShardingStrategyConfig> tableShardings = new ArrayList<ShardingStrategyConfig>();
        tableShardings.add(shardingConfig);
        queryExecutor.getInnerModel().tableShardings = tableShardings;
    }
    DataSource realDataSource = getDataSource(queryExecutor.getInnerModel().dataSource, sqlToyConfig);
    // 取count数量
    if (isCount) {
        return dialectFactory.getCountBySql(sqlToyContext, queryExecutor, sqlToyConfig, realDataSource);
    }
    // 非分页
    if (page == null) {
        // 取top
        if (innerModel.pickType == 0) {
            return dialectFactory.findTop(sqlToyContext, queryExecutor, sqlToyConfig, innerModel.pickSize, realDataSource).getRows();
        } else // 取随机记录
        if (innerModel.pickType == 1) {
            return dialectFactory.getRandomResult(sqlToyContext, queryExecutor, sqlToyConfig, innerModel.pickSize, realDataSource).getRows();
        } else {
            return dialectFactory.findByQuery(sqlToyContext, queryExecutor, sqlToyConfig, innerModel.lockMode, realDataSource).getRows();
        }
    }
    // 跳过总记录数形式的分页
    if (page.getSkipQueryCount()) {
        return dialectFactory.findSkipTotalCountPage(sqlToyContext, queryExecutor, sqlToyConfig, page.getPageNo(), page.getPageSize(), realDataSource).getPageResult();
    }
    return dialectFactory.findPage(sqlToyContext, queryExecutor, sqlToyConfig, page.getPageNo(), page.getPageSize(), realDataSource).getPageResult();
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) SqlToyConfig(org.sagacity.sqltoy.config.model.SqlToyConfig) ArrayList(java.util.ArrayList) DataSource(javax.sql.DataSource) Entry(java.util.Map.Entry) ParallQueryExecutor(org.sagacity.sqltoy.dialect.executor.ParallQueryExecutor) QueryExecutor(org.sagacity.sqltoy.model.QueryExecutor) ShardingStrategyConfig(org.sagacity.sqltoy.config.model.ShardingStrategyConfig) TranslateExtend(org.sagacity.sqltoy.model.inner.TranslateExtend) EntityQueryExtend(org.sagacity.sqltoy.model.inner.EntityQueryExtend) Translate(org.sagacity.sqltoy.config.model.Translate) HashSet(java.util.HashSet)

Example 42 with EntityMeta

use of org.sagacity.sqltoy.config.model.EntityMeta in project sagacity-sqltoy by chenrenfei.

the class SqlToyDaoSupport method loadByIds.

/**
 * @TODO 通过id集合批量加载对象
 * @param <T>
 * @param voClass
 * @param lockMode
 * @param ids
 * @return
 */
protected <T extends Serializable> List<T> loadByIds(final Class<T> voClass, final LockMode lockMode, Object... ids) {
    if (voClass == null || ids == null || ids.length == 0) {
        throw new IllegalArgumentException("voClass、ids must not null!");
    }
    EntityMeta entityMeta = getEntityMeta(voClass);
    if (entityMeta == null || entityMeta.getIdArray() == null || entityMeta.getIdArray().length != 1) {
        throw new IllegalArgumentException("voClass must is entity with @SqlToyEntity and must has primary key!");
    }
    List<T> entities = BeanUtil.wrapEntities(sqlToyContext.getTypeHandler(), entityMeta, voClass, ids);
    return dialectFactory.loadAll(sqlToyContext, entities, null, lockMode, this.getDataSource(null));
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta)

Example 43 with EntityMeta

use of org.sagacity.sqltoy.config.model.EntityMeta in project sagacity-sqltoy by chenrenfei.

the class SqlToyDaoSupport method deleteByQuery.

/**
 * @TODO 提供单表简易查询进行删除操作(删除操作filters过滤无效)
 * @param entityClass
 * @param entityQuery
 * @return
 */
protected Long deleteByQuery(Class entityClass, EntityQuery entityQuery) {
    EntityQueryExtend innerModel = entityQuery.getInnerModel();
    if (null == entityClass || null == entityQuery || StringUtil.isBlank(innerModel.where) || StringUtil.isBlank(innerModel.values)) {
        throw new IllegalArgumentException("deleteByQuery entityClass、where、value 值不能为空!");
    }
    // 做一个必要提示
    if (!innerModel.paramFilters.isEmpty()) {
        logger.warn("删除操作设置动态条件过滤是无效的,数据删除查询条件必须是精准的!");
    }
    EntityMeta entityMeta = getEntityMeta(entityClass);
    String where = SqlUtil.convertFieldsToColumns(entityMeta, innerModel.where);
    String sql = "delete from ".concat(entityMeta.getSchemaTable(null, null)).concat(" where ").concat(where);
    SqlToyConfig sqlToyConfig = getSqlToyConfig(sql, SqlType.update);
    QueryExecutor queryExecutor = null;
    // :named 模式
    if (SqlConfigParseUtils.hasNamedParam(where) && StringUtil.isBlank(innerModel.names)) {
        queryExecutor = new QueryExecutor(sql, (Serializable) innerModel.values[0]);
    } else {
        queryExecutor = new QueryExecutor(sql).names(innerModel.names).values(innerModel.values);
    }
    if (innerModel.paramFilters != null && innerModel.paramFilters.size() > 0) {
        queryExecutor.getInnerModel().paramFilters.addAll(innerModel.paramFilters);
    }
    // 分库分表策略
    setEntitySharding(queryExecutor, entityMeta);
    return dialectFactory.executeSql(sqlToyContext, sqlToyConfig, queryExecutor, null, null, getDataSource(innerModel.dataSource));
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) Serializable(java.io.Serializable) SqlToyConfig(org.sagacity.sqltoy.config.model.SqlToyConfig) ParallQueryExecutor(org.sagacity.sqltoy.dialect.executor.ParallQueryExecutor) QueryExecutor(org.sagacity.sqltoy.model.QueryExecutor) EntityQueryExtend(org.sagacity.sqltoy.model.inner.EntityQueryExtend)

Example 44 with EntityMeta

use of org.sagacity.sqltoy.config.model.EntityMeta in project sagacity-sqltoy by chenrenfei.

the class SqlToyDaoSupport method generateBizId.

/**
 * @todo 根据实体对象对应的POJO配置的业务主键策略,提取对象的属性值产生业务主键
 * @param entity
 * @return
 */
protected String generateBizId(Serializable entity) {
    EntityMeta entityMeta = this.getEntityMeta(entity.getClass());
    if (entityMeta == null || !entityMeta.isHasBizIdConfig()) {
        throw new IllegalArgumentException(StringUtil.fillArgs("对象:{},没有配置业务主键生成策略,请检查POJO 的业务主键配置!", entity.getClass().getName()));
    }
    String businessIdType = entityMeta.getColumnJavaType(entityMeta.getBusinessIdField());
    Integer[] relatedColumn = entityMeta.getBizIdRelatedColIndex();
    Object[] fullParamValues = BeanUtil.reflectBeanToAry(entity, entityMeta.getFieldsArray());
    // 提取关联属性的值
    Object[] relatedColValue = null;
    if (relatedColumn != null) {
        relatedColValue = new Object[relatedColumn.length];
        for (int meter = 0; meter < relatedColumn.length; meter++) {
            relatedColValue[meter] = fullParamValues[relatedColumn[meter]];
            if (relatedColValue[meter] == null) {
                throw new IllegalArgumentException("对象:" + entity.getClass().getName() + " 生成业务主键依赖的关联字段:" + relatedColumn[meter] + " 值为null!");
            }
        }
    }
    IdGenerator idGenerator = (entityMeta.getBusinessIdGenerator() == null) ? entityMeta.getIdGenerator() : entityMeta.getBusinessIdGenerator();
    return idGenerator.getId(entityMeta.getTableName(), entityMeta.getBizIdSignature(), entityMeta.getBizIdRelatedColumns(), relatedColValue, new Date(), businessIdType, entityMeta.getBizIdLength(), entityMeta.getBizIdSequenceSize()).toString();
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) RedisIdGenerator(org.sagacity.sqltoy.plugins.id.impl.RedisIdGenerator) IdGenerator(org.sagacity.sqltoy.plugins.id.IdGenerator) Date(java.util.Date)

Example 45 with EntityMeta

use of org.sagacity.sqltoy.config.model.EntityMeta in project sagacity-sqltoy by chenrenfei.

the class SqlToyDaoSupport method updateByQuery.

/**
 * @TODO 针对单表对象查询进行更新操作(update和delete 操作filters过滤是无效的,必须是精准的条件参数)
 * @param entityClass
 * @param entityUpdate
 * @update 2021-12-23 支持update table set field=field+1等计算模式
 * @return
 */
protected Long updateByQuery(Class entityClass, EntityUpdate entityUpdate) {
    if (null == entityClass || null == entityUpdate || StringUtil.isBlank(entityUpdate.getInnerModel().where) || StringUtil.isBlank(entityUpdate.getInnerModel().values) || entityUpdate.getInnerModel().updateValues.isEmpty()) {
        throw new IllegalArgumentException("updateByQuery: entityClass、where条件、条件值value、变更值setValues不能为空!");
    }
    EntityUpdateExtend innerModel = entityUpdate.getInnerModel();
    boolean isName = SqlConfigParseUtils.hasNamedParam(innerModel.where);
    Object[] values = innerModel.values;
    String[] paramNames = null;
    String where = innerModel.where;
    int valueSize = (values == null) ? 0 : values.length;
    // 重新通过对象反射获取参数条件的值
    if (isName) {
        if (values.length > 1) {
            throw new IllegalArgumentException("updateByQuery: where条件采用:paramName形式传参,values只能传递单个VO或Map对象!");
        }
        paramNames = SqlConfigParseUtils.getSqlParamsName(where, false);
        values = BeanUtil.reflectBeanToAry(values[0], paramNames);
        // 重新设置值数组的长度
        valueSize = values.length;
    } else {
        if (DialectUtils.getParamsCount(where) != valueSize) {
            throw new IllegalArgumentException("updateByQuery: where语句中的?数量跟对应values 数组长度不一致,请检查!");
        }
    }
    EntityMeta entityMeta = getEntityMeta(entityClass);
    // 处理where 中写的java 字段名称为数据库表字段名称
    where = SqlUtil.convertFieldsToColumns(entityMeta, where);
    StringBuilder sql = new StringBuilder();
    sql.append("update ").append(entityMeta.getSchemaTable(null, null)).append(" set ");
    Entry<String, Object> entry;
    // 对统一更新字段做处理
    IUnifyFieldsHandler unifyHandler = getSqlToyContext().getUnifyFieldsHandler();
    if (unifyHandler != null) {
        Map<String, Object> updateFields = unifyHandler.updateUnifyFields();
        if (updateFields != null && !updateFields.isEmpty()) {
            Iterator<Entry<String, Object>> updateIter = updateFields.entrySet().iterator();
            while (updateIter.hasNext()) {
                entry = updateIter.next();
                // 是数据库表的字段
                if (entityMeta.getColumnName(entry.getKey()) != null) {
                    // 是否已经主动update
                    if (innerModel.updateValues.containsKey(entry.getKey())) {
                        // 判断是否存在强制更新
                        if (unifyHandler.forceUpdateFields() != null && unifyHandler.forceUpdateFields().contains(entry.getKey())) {
                            innerModel.updateValues.put(entry.getKey(), entry.getValue());
                        }
                    } else {
                        innerModel.updateValues.put(entry.getKey(), entry.getValue());
                    }
                }
            }
        }
    }
    Object[] realValues = new Object[innerModel.updateValues.size() + valueSize];
    if (valueSize > 0) {
        System.arraycopy(values, 0, realValues, innerModel.updateValues.size(), valueSize);
    }
    Integer[] paramsTypes = new Integer[realValues.length];
    for (int i = 0; i < paramsTypes.length; i++) {
        paramsTypes[i] = java.sql.Types.OTHER;
    }
    String[] realNames = null;
    if (isName) {
        realNames = new String[realValues.length];
        System.arraycopy(paramNames, 0, realNames, innerModel.updateValues.size(), valueSize);
    }
    int index = 0;
    String columnName;
    FieldMeta fieldMeta;
    Iterator<Entry<String, Object>> iter = innerModel.updateValues.entrySet().iterator();
    String[] fields;
    String fieldSetValue;
    // 设置一个扩展标志,避免set field=field+? 场景构造成field=field+:fieldExtParam跟where
    // field=:field名称冲突
    final String extSign = "ExtParam";
    while (iter.hasNext()) {
        entry = iter.next();
        // 考虑 field=filed+? 模式,分割成2部分
        fields = entry.getKey().split("=");
        fieldMeta = entityMeta.getFieldMeta(fields[0].trim());
        // entry.getKey() 直接是数据库字段名称
        if (fieldMeta == null) {
            // 先通过数据字段名称获得类的属性名称再获取fieldMeta
            fieldMeta = entityMeta.getFieldMeta(entityMeta.getColumnFieldMap().get(fields[0].trim().toLowerCase()));
        }
        columnName = fieldMeta.getColumnName();
        // 设置字段类型
        if (fields.length == 1) {
            paramsTypes[index] = fieldMeta.getType();
        }
        // 保留字处理
        columnName = ReservedWordsUtil.convertWord(columnName, null);
        if (isName) {
            if (fields.length > 1) {
                if (fields[1].contains("?")) {
                    // 拼接扩展字符,避免where后面有同样的参数名称
                    realNames[index] = fieldMeta.getFieldName().concat(extSign);
                } else {
                    realNames[index] = SqlConfigParseUtils.getSqlParamsName(fields[1], true)[0];
                }
            } else {
                realNames[index] = fieldMeta.getFieldName();
            }
        }
        realValues[index] = entry.getValue();
        if (index > 0) {
            sql.append(",");
        }
        if (fields.length == 1) {
            sql.append(columnName).append("=").append(isName ? (":" + fieldMeta.getFieldName()) : "?");
        } else {
            // field=filed+? 类似模式
            fieldSetValue = fields[1];
            sql.append(columnName).append("=");
            if (isName && fieldSetValue.contains("?")) {
                fieldSetValue = fieldSetValue.replace("?", ":" + fieldMeta.getFieldName().concat(extSign));
            }
            fieldSetValue = SqlUtil.convertFieldsToColumns(entityMeta, fieldSetValue);
            sql.append(fieldSetValue);
        }
        index++;
    }
    sql.append(" where ").append(where);
    String sqlStr = sql.toString();
    SqlToyConfig sqlToyConfig = sqlToyContext.getSqlToyConfig(sqlStr, SqlType.update, getDialect(innerModel.dataSource));
    QueryExecutor queryExecutor = new QueryExecutor(sqlStr).names(realNames).values(realValues);
    setEntitySharding(queryExecutor, entityMeta);
    return dialectFactory.executeSql(sqlToyContext, sqlToyConfig, queryExecutor, paramsTypes, null, getDataSource(innerModel.dataSource, sqlToyConfig));
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) SqlToyConfig(org.sagacity.sqltoy.config.model.SqlToyConfig) FieldMeta(org.sagacity.sqltoy.config.model.FieldMeta) EntityUpdateExtend(org.sagacity.sqltoy.model.inner.EntityUpdateExtend) IUnifyFieldsHandler(org.sagacity.sqltoy.plugins.IUnifyFieldsHandler) Entry(java.util.Map.Entry) ParallQueryExecutor(org.sagacity.sqltoy.dialect.executor.ParallQueryExecutor) QueryExecutor(org.sagacity.sqltoy.model.QueryExecutor)

Aggregations

EntityMeta (org.sagacity.sqltoy.config.model.EntityMeta)141 SavePKStrategy (org.sagacity.sqltoy.dialect.model.SavePKStrategy)36 PKStrategy (org.sagacity.sqltoy.config.model.PKStrategy)28 GenerateSavePKStrategy (org.sagacity.sqltoy.callback.GenerateSavePKStrategy)24 ArrayList (java.util.ArrayList)23 Serializable (java.io.Serializable)22 SqlToyConfig (org.sagacity.sqltoy.config.model.SqlToyConfig)22 List (java.util.List)20 GenerateSqlHandler (org.sagacity.sqltoy.callback.GenerateSqlHandler)20 GenerateSqlHandler (org.sagacity.sqltoy.dialect.handler.GenerateSqlHandler)13 GenerateSavePKStrategy (org.sagacity.sqltoy.dialect.handler.GenerateSavePKStrategy)12 IOException (java.io.IOException)11 SQLException (java.sql.SQLException)11 HashMap (java.util.HashMap)11 TableCascadeModel (org.sagacity.sqltoy.config.model.TableCascadeModel)10 ReturnPkType (org.sagacity.sqltoy.dialect.model.ReturnPkType)10 OneToManyModel (org.sagacity.sqltoy.config.model.OneToManyModel)8 SqlToyResult (org.sagacity.sqltoy.config.model.SqlToyResult)8 Type (java.lang.reflect.Type)6 PreparedStatement (java.sql.PreparedStatement)6