Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.gitee.qdbp.jdbc.biz.CrudDaoImpl Maven / Gradle / Ivy
package com.gitee.qdbp.jdbc.biz;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitee.qdbp.able.convert.MapToBeanConverter;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.jdbc.condition.DbUpdate;
import com.gitee.qdbp.able.jdbc.condition.DbWhere;
import com.gitee.qdbp.able.jdbc.fields.Fields;
import com.gitee.qdbp.able.jdbc.fields.IncludeFields;
import com.gitee.qdbp.able.jdbc.model.PkEntity;
import com.gitee.qdbp.able.jdbc.ordering.Orderings;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.jdbc.api.CrudDao;
import com.gitee.qdbp.jdbc.api.SqlBoot;
import com.gitee.qdbp.jdbc.api.SqlBufferJdbcOperations;
import com.gitee.qdbp.jdbc.api.SqlDao;
import com.gitee.qdbp.jdbc.api.SqlOperator;
import com.gitee.qdbp.jdbc.exception.DbErrorCode;
import com.gitee.qdbp.jdbc.model.AllFieldColumn;
import com.gitee.qdbp.jdbc.model.DbVersion;
import com.gitee.qdbp.jdbc.model.FieldScene;
import com.gitee.qdbp.jdbc.model.SimpleFieldColumn;
import com.gitee.qdbp.jdbc.model.ValidStrategy;
import com.gitee.qdbp.jdbc.plugins.BatchInsertExecutor;
import com.gitee.qdbp.jdbc.plugins.BatchUpdateExecutor;
import com.gitee.qdbp.jdbc.plugins.DbConditionConverter;
import com.gitee.qdbp.jdbc.plugins.DbPluginHelper;
import com.gitee.qdbp.jdbc.plugins.EntityDataStateFillStrategy;
import com.gitee.qdbp.jdbc.plugins.EntityFieldFillExecutor;
import com.gitee.qdbp.jdbc.plugins.EntityFieldFillStrategy;
import com.gitee.qdbp.jdbc.plugins.SqlDialect;
import com.gitee.qdbp.jdbc.sql.SqlBuffer;
import com.gitee.qdbp.jdbc.sql.SqlBuilder;
import com.gitee.qdbp.jdbc.sql.SqlTools;
import com.gitee.qdbp.jdbc.sql.build.CommonSqlTools;
import com.gitee.qdbp.jdbc.sql.build.CrudSqlHelper;
import com.gitee.qdbp.jdbc.sql.fragment.CrudFragmentHelper;
import com.gitee.qdbp.jdbc.sql.parse.SqlFragmentContainer;
import com.gitee.qdbp.jdbc.utils.ParseTools;
import com.gitee.qdbp.tools.utils.ConvertTools;
import com.gitee.qdbp.tools.utils.MapTools;
import com.gitee.qdbp.tools.utils.VerifyTools;
/**
* 基础增删改查数据库操作
*
* @author 赵卉华
* @version 190601
*/
public class CrudDaoImpl extends BaseQueryerImpl implements CrudDao {
private static final Logger log = LoggerFactory.getLogger(CrudDaoImpl.class);
protected final Class beanClass;
protected final SqlBoot sqlBoot;
protected final SqlDao sqlDao;
protected final CrudSqlOperator sqlOperator;
/** 批量执行时的大小限制(0为无限制) **/
protected int defaultBatchSize = QdbcBootImpl.DEFAULT_BATCH_SIZE;
CrudDaoImpl(Class c, SqlBoot sqlBoot, SqlDao sqlDao, SqlBufferJdbcOperations jdbc) {
super(new CrudSqlHelper(c, sqlBoot), newEntityFieldFillExecutor(c, sqlBoot), jdbc,
sqlBoot.plugins().getRowToBeanMapper(c));
this.beanClass = c;
this.sqlBoot = sqlBoot;
this.sqlDao = sqlDao;
this.sqlOperator = new CrudSqlOperator(c, sqlBoot);
}
private static EntityFieldFillExecutor newEntityFieldFillExecutor(Class> clazz, SqlBoot sqlBoot) {
DbPluginHelper plugins = sqlBoot.plugins();
AllFieldColumn> allFields = plugins.parseAllFieldColumns(clazz);
EntityFieldFillStrategy fieldFillStrategy = plugins.getEntityFieldFillStrategy();
EntityDataStateFillStrategy> dataStateFillStrategy = plugins.getEntityDataStateFillStrategy();
return new EntityFieldFillExecutor(allFields, fieldFillStrategy, dataStateFillStrategy);
}
@Override
public CrudSqlHelper sqlHelper() {
return (CrudSqlHelper) this.sqlHelper;
}
@Override
public T findById(Serializable id) {
return findById(Fields.ALL, id);
}
@Override
public T findById(Fields fields, Serializable id) {
VerifyTools.requireNotBlank(id, "id");
SimpleFieldColumn pk = sqlHelper().fragment().getPrimaryKey();
if (pk == null) { // 没有找到主键字段
String details = "UnsupportedFindById, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_FIELD_IS_UNRESOLVED).setDetails(details);
}
String primaryField = pk.getFieldName();
DbWhere where = new DbWhere().on(primaryField).equals(id).end();
return this.find(fields, where);
}
@Override
public List listByIds(Collection extends Serializable> ids, Orderings orderings) throws ServiceException {
VerifyTools.requireNotBlank(ids, "ids");
return listByIds(Fields.ALL, ids, orderings);
}
@Override
public List listByIds(Fields fields, Collection extends Serializable> ids, Orderings orderings)
throws ServiceException {
SimpleFieldColumn pk = sqlHelper().fragment().getPrimaryKey();
if (pk == null) { // 没有找到主键字段
String details = "UnsupportedListByIds, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_FIELD_IS_UNRESOLVED).setDetails(details);
}
String primaryField = pk.getFieldName();
DbWhere where = new DbWhere().on(primaryField).in(ids).end();
return list(fields, where, orderings);
}
@Override
public List listChildren(String startCode, String codeField, String parentField, DbWhere filterWhere,
DbWhere searchWhere, Orderings orderings) {
VerifyTools.requireNotBlank(startCode, "startCode");
VerifyTools.requireNotBlank(codeField, "codeField");
VerifyTools.requireNotBlank(parentField, "parentField");
List startCodes = Collections.singletonList(startCode);
return doListChildren(startCodes, codeField, parentField, filterWhere, searchWhere, orderings);
}
@Override
public List listChildren(List startCodes, String codeField, String parentField, DbWhere filterWhere,
DbWhere searchWhere, Orderings orderings) {
VerifyTools.requireNotBlank(startCodes, "startCodes");
VerifyTools.requireNotBlank(codeField, "codeField");
VerifyTools.requireNotBlank(parentField, "parentField");
return doListChildren(startCodes, codeField, parentField, filterWhere, searchWhere, orderings);
}
private List doListChildren(List startCodes, String codeField, String parentField, DbWhere filterWhere,
DbWhere searchWhere, Orderings orderings) {
DbWhere filter = checkWhere(filterWhere);
DbWhere search = checkWhere(searchWhere);
// 数据状态填充在filterWhere中
entityFieldFillExecutor.fillQueryWhereDataState(filter, getMajorTableAlias());
// 数据权限填充在searchWhere中
entityFieldFillExecutor.fillQueryWhereParams(search, getMajorTableAlias());
return doListChildren(startCodes, codeField, parentField, Fields.ALL, filter, search, orderings, beanClass);
}
@Override
public List listChildrenCodes(String startCode, String codeField, String parentField, DbWhere filterWhere,
DbWhere searchWhere, Orderings orderings) {
VerifyTools.requireNotBlank(startCode, "startCode");
VerifyTools.requireNotBlank(codeField, "codeField");
VerifyTools.requireNotBlank(parentField, "parentField");
List startCodes = Collections.singletonList(startCode);
return doListChildrenCodes(startCodes, codeField, parentField, filterWhere, searchWhere, orderings);
}
@Override
public List listChildrenCodes(List startCodes, String codeField, String parentField,
DbWhere filterWhere, DbWhere searchWhere, Orderings orderings) {
VerifyTools.requireNotBlank(startCodes, "startCodes");
VerifyTools.requireNotBlank(codeField, "codeField");
VerifyTools.requireNotBlank(parentField, "parentField");
return doListChildrenCodes(startCodes, codeField, parentField, filterWhere, searchWhere, orderings);
}
private List doListChildrenCodes(List startCodes, String codeField, String parentField,
DbWhere filterWhere, DbWhere searchWhere, Orderings orderings) {
DbWhere filter = checkWhere(filterWhere);
DbWhere search = checkWhere(searchWhere);
// 数据状态填充在filterWhere中
entityFieldFillExecutor.fillQueryWhereDataState(filter, getMajorTableAlias());
// 数据权限填充在searchWhere中
entityFieldFillExecutor.fillQueryWhereParams(search, getMajorTableAlias());
IncludeFields fields = new IncludeFields(codeField);
return doListChildren(startCodes, codeField, parentField, fields, filter, search, orderings, String.class);
}
@Override
public List listParents(String startCode, String codeField, String parentField, DbWhere filterWhere,
DbWhere searchWhere, Orderings orderings) {
VerifyTools.requireNotBlank(startCode, "startCode");
VerifyTools.requireNotBlank(codeField, "codeField");
VerifyTools.requireNotBlank(parentField, "parentField");
List startCodes = Collections.singletonList(startCode);
return doListParents(startCodes, codeField, parentField, filterWhere, searchWhere, orderings);
}
@Override
public List listParents(List startCodes, String codeField, String parentField, DbWhere filterWhere,
DbWhere searchWhere, Orderings orderings) {
VerifyTools.requireNotBlank(startCodes, "startCodes");
VerifyTools.requireNotBlank(codeField, "codeField");
VerifyTools.requireNotBlank(parentField, "parentField");
return doListParents(startCodes, codeField, parentField, filterWhere, searchWhere, orderings);
}
private List doListParents(List startCodes, String codeField, String parentField, DbWhere filterWhere,
DbWhere searchWhere, Orderings orderings) {
DbWhere filter = checkWhere(filterWhere);
DbWhere search = checkWhere(searchWhere);
// 数据状态填充在filterWhere中
entityFieldFillExecutor.fillQueryWhereDataState(filter, getMajorTableAlias());
// 数据权限填充在searchWhere中
entityFieldFillExecutor.fillQueryWhereParams(search, getMajorTableAlias());
if (orderings != null && !orderings.isEmpty()) {
return doListParents(startCodes, codeField, parentField, Fields.ALL, filter, search, orderings, beanClass);
} else {
// 如果startCode只有一个, 且未指定排序字段, 则结果会保证顺序从顶级节点开始依次排列
Map params = generateRecursiveParams(startCodes, codeField, parentField, Fields.ALL,
filterWhere, searchWhere, orderings);
String sqlId = "GlobalRecursive:recursiveListParentsQuery";
List> list = sqlDao.listForMaps(sqlId, params);
List> sorted = MapTools.sortTreeNodes(list, codeField, parentField);
List results = new ArrayList<>();
MapToBeanConverter converter = sqlBoot.plugins().getMapToBeanConverter();
for (Map item : sorted) {
T entity = converter.convert(item, beanClass);
results.add(entity);
}
return results;
}
}
@Override
public List listParentCodes(String startCode, String codeField, String parentField, DbWhere filterWhere,
DbWhere searchWhere, Orderings orderings) {
VerifyTools.requireNotBlank(startCode, "startCode");
VerifyTools.requireNotBlank(codeField, "codeField");
VerifyTools.requireNotBlank(parentField, "parentField");
List startCodes = Collections.singletonList(startCode);
return doListParentCodes(startCodes, codeField, parentField, filterWhere, searchWhere, orderings);
}
@Override
public List listParentCodes(List startCodes, String codeField, String parentField,
DbWhere filterWhere, DbWhere searchWhere, Orderings orderings) {
VerifyTools.requireNotBlank(startCodes, "startCodes");
VerifyTools.requireNotBlank(codeField, "codeField");
VerifyTools.requireNotBlank(parentField, "parentField");
return doListParentCodes(startCodes, codeField, parentField, filterWhere, searchWhere, orderings);
}
private List doListParentCodes(List startCodes, String codeField, String parentField,
DbWhere filterWhere,
DbWhere searchWhere, Orderings orderings) {
DbWhere filter = checkWhere(filterWhere);
DbWhere search = checkWhere(searchWhere);
// 数据状态填充在filterWhere中
entityFieldFillExecutor.fillQueryWhereDataState(filter, getMajorTableAlias());
// 数据权限填充在searchWhere中
entityFieldFillExecutor.fillQueryWhereParams(search, getMajorTableAlias());
if (orderings != null && !orderings.isEmpty()) {
IncludeFields fields = new IncludeFields(codeField);
return doListParents(startCodes, codeField, parentField, fields, filter, search, orderings,
String.class);
} else {
IncludeFields fields = new IncludeFields(codeField, parentField);
Map params = generateRecursiveParams(startCodes, codeField, parentField, fields,
filterWhere, searchWhere, orderings);
String sqlId = "GlobalRecursive:recursiveListParentsQuery";
List> list = sqlDao.listForMaps(sqlId, params);
List> sorted = MapTools.sortTreeNodes(list, codeField, parentField);
List results = new ArrayList<>();
for (Map item : sorted) {
Object codeValue = item.get(codeField);
if (codeValue != null) {
results.add(codeValue.toString());
}
}
return results;
}
}
// ORACLE: START WITH {codeField} IN( {startCode} ) CONNECT BY PRIOR {codeField}={parentField}
// DB2: 使用WITH递归
// MYSQL 8.0+: 使用WITH RECURSIVE递归
// MYSQL 8.0-: 使用存储过程RECURSIVE_LIST_CHILDREN_QUERY
protected List doListChildren(List startCodes, String codeField, String parentField, Fields fields,
DbWhere filter, DbWhere search, Orderings orderings, Class resultType) throws ServiceException {
return doListRecursive("Children", startCodes, codeField, parentField, fields, filter, search, orderings,
resultType);
}
protected List doListParents(List startCodes, String codeField, String parentField, Fields fields,
DbWhere filter, DbWhere search, Orderings orderings, Class resultType) throws ServiceException {
return doListRecursive("Parents", startCodes, codeField, parentField, fields, filter, search, orderings,
resultType);
}
protected List doListRecursive(String type, List startCodes, String codeField, String parentField,
Fields selectFields, DbWhere filterWhere, DbWhere searchWhere, Orderings orderings, Class resultType)
throws ServiceException {
Map params = generateRecursiveParams(startCodes, codeField, parentField, selectFields,
filterWhere, searchWhere, orderings);
String sqlId = "GlobalRecursive:recursiveList" + type + "Query";
return sqlDao.listForObjects(sqlId, params, resultType);
}
private Map generateRecursiveParams(List startCodes, String codeField, String parentField,
Fields selectFields, DbWhere filterWhere, DbWhere searchWhere, Orderings orderings) {
CrudFragmentHelper sqlHelper = sqlHelper().fragment();
String codeColumn = sqlHelper.getColumnName(FieldScene.CONDITION, codeField);
String parentColumn = sqlHelper.getColumnName(FieldScene.CONDITION, parentField);
SqlBuffer selectColumns = sqlHelper.buildSelectFieldsSql(selectFields);
Map params = new HashMap<>();
params.put("codeColumn", codeColumn);
params.put("parentColumn", parentColumn);
params.put("tableName", sqlHelper.getTableName());
params.put("selectColumns", selectColumns);
params.put("startCodes", startCodes);
if (filterWhere != null && !filterWhere.isEmpty()) {
params.put("filterWhere", sqlHelper.buildWhereSql(filterWhere, false));
}
if (searchWhere != null && !searchWhere.isEmpty()) {
params.put("searchWhere", sqlHelper.buildWhereSql(searchWhere, false));
}
if (orderings != null && !orderings.isEmpty()) {
params.put("orderBy", sqlHelper.buildOrderBySql(orderings, false));
}
return params;
}
protected Map copmareMapDifference(Map original, Map current) {
Map diff = new HashMap<>();
for (Map.Entry entry : original.entrySet()) {
if (!current.containsKey(entry.getKey())) {
diff.put(entry.getKey(), null);
}
}
for (Map.Entry entry : current.entrySet()) {
Object curvalue = SqlTools.unwrapDbVariable(entry.getValue());
Object orivalue = SqlTools.unwrapDbVariable(original.get(entry.getKey()));
if (VerifyTools.notEquals(curvalue, orivalue)) {
diff.put(entry.getKey(), curvalue);
}
}
return diff;
}
@Override
public String insert(T entity) throws ServiceException {
VerifyTools.requireNonNull(entity, "entity");
return executeInsert(entity, ValidStrategy.AUTO, true);
}
@Override
public String insert(T entity, boolean fillCreateParams) throws ServiceException {
VerifyTools.requireNonNull(entity, "entity");
return executeInsert(entity, ValidStrategy.AUTO, fillCreateParams);
}
@Override
public String insert(Map entity) throws ServiceException {
VerifyTools.requireNonNull(entity, "entity");
return executeInsert(entity, ValidStrategy.AUTO, true);
}
@Override
public String insert(Map entity, boolean fillCreateParams) throws ServiceException {
VerifyTools.requireNonNull(entity, "entity");
return executeInsert(entity, ValidStrategy.AUTO, fillCreateParams);
}
@Override
public String insert(T entity, ValidStrategy validStrategy) throws ServiceException {
VerifyTools.requireNonNull(entity, "entity");
return executeInsert(entity, validStrategy, true);
}
@Override
public String insert(T entity, ValidStrategy validStrategy, boolean fillCreateParams) throws ServiceException {
VerifyTools.requireNonNull(entity, "entity");
return executeInsert(entity, validStrategy, fillCreateParams);
}
@Override
public String insert(Map entity, ValidStrategy validStrategy) throws ServiceException {
VerifyTools.requireNonNull(entity, "entity");
return executeInsert(entity, validStrategy, true);
}
@Override
public String insert(Map entity, ValidStrategy validStrategy, boolean fillCreateParams)
throws ServiceException {
VerifyTools.requireNonNull(entity, "entity");
return executeInsert(entity, validStrategy, fillCreateParams);
}
protected String executeInsert(Object object, ValidStrategy validStrategy, boolean fillCreateParams)
throws ServiceException {
// 将实体类转换为map, 并执行实体业务数据填充
PkEntity pe = convertAndFillCreateParams(object, fillCreateParams);
String id = pe.getPrimaryKey();
Map readyEntity = pe.getEntity();
// 执行数据库插入
SqlBuffer buffer = sqlHelper().buildInsertSql(readyEntity, validStrategy);
jdbc.insert(buffer);
return id;
}
@Override
public List inserts(List> entities) throws ServiceException {
return doInserts(entities, ValidStrategy.AUTO, true, this.defaultBatchSize);
}
@Override
public List inserts(List> entities, boolean fillCreateParams) throws ServiceException {
return doInserts(entities, ValidStrategy.AUTO, fillCreateParams, this.defaultBatchSize);
}
@Override
public List inserts(List> entities, ValidStrategy validStrategy) throws ServiceException {
return doInserts(entities, validStrategy, true, this.defaultBatchSize);
}
@Override
public List inserts(List> entities, ValidStrategy validStrategy, boolean fillCreateParams)
throws ServiceException {
return doInserts(entities, validStrategy, fillCreateParams, this.defaultBatchSize);
}
protected List doInserts(List> entities, ValidStrategy validStrategy, boolean fillCreateParams,
int batchSize) throws ServiceException {
VerifyTools.requireNotBlank(entities, "entities");
if (entities.size() == 1) {
Object first = entities.get(0);
String id = executeInsert(first, validStrategy, fillCreateParams);
return ConvertTools.toList(id);
} else if (batchSize <= 0 || entities.size() <= batchSize) {
return doBatchInserts(entities, validStrategy, fillCreateParams);
} else { // 分批导入
List ids = new ArrayList<>();
List buffer = new ArrayList<>();
for (int i = 1, size = entities.size(); i <= size; i++) {
buffer.add(entities.get(i - 1));
if (i % batchSize == 0 || i == size) {
List batchIds = doBatchInserts(buffer, validStrategy, fillCreateParams);
ids.addAll(batchIds);
buffer.clear();
}
}
return ids;
}
}
protected List doBatchInserts(List> entities, ValidStrategy validStrategy, boolean fillCreateParams)
throws ServiceException {
List contents = new ArrayList<>();
for (Object item : entities) {
// 将实体类转换为map, 并执行实体业务数据填充
PkEntity pe = convertAndFillCreateParams(item, fillCreateParams);
contents.add(pe);
}
DbVersion version = jdbc.dbVersion();
BatchInsertExecutor batchOperator = jdbc.plugins().getBatchInsertExecutor(version);
// 执行批量数据库插入
return batchOperator.inserts(contents, validStrategy, jdbc, sqlOperator);
}
@Override
public int update(T entity) throws ServiceException {
return this.update(entity, ValidStrategy.AUTO, true, false);
}
@Override
public int update(T entity, boolean fillUpdateParams, boolean errorOnUnaffected) throws ServiceException {
return this.update(entity, ValidStrategy.AUTO, fillUpdateParams, fillUpdateParams);
}
@Override
public int update(T entity, ValidStrategy validStrategy) throws ServiceException {
return this.update(entity, validStrategy, true, false);
}
@Override
public int update(T entity, ValidStrategy validStrategy, boolean fillUpdateParams, boolean errorOnUnaffected)
throws ServiceException {
if (entity == null) {
log.debug("Update set fields is empty, the update operation will be skipped.");
return 0;
}
// 查找主键
SimpleFieldColumn pk = sqlHelper().fragment().getPrimaryKey();
if (pk == null) { // 没有找到主键字段
String details = "UnsupportedUpdateById, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_FIELD_IS_UNRESOLVED).setDetails(details);
}
PkEntity pe = convertAndFillUpdateParams(entity, fillUpdateParams);
Serializable pkValue = pe.getPrimaryKey();
if (VerifyTools.isBlank(pkValue)) { // 主键值为空
String details = "CanNotExecuteUpdateById, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_VALUE_IS_REQUIRED).setDetails(details);
}
// 实体类转换为DbUpdate
DbConditionConverter converter = jdbc.plugins().getDbConditionConverter();
DbUpdate ud = converter.parseMapToDbUpdate(pe.getEntity());
// 生成主键限制条件
DbWhere where = new DbWhere().on(pk.getFieldName()).equals(pkValue).end();
entityFieldFillExecutor.fillUpdateWhereDataState(where);
entityFieldFillExecutor.fillUpdateWhereParams(where);
return this.doUpdate(ud, where, validStrategy, errorOnUnaffected);
}
@Override
public int update(Map entity) throws ServiceException {
return this.update(entity, ValidStrategy.AUTO, true, false);
}
@Override
public int update(Map entity, boolean fillUpdateParams, boolean errorOnUnaffected)
throws ServiceException {
return this.update(entity, ValidStrategy.AUTO, fillUpdateParams, errorOnUnaffected);
}
@Override
public int update(Map entity, ValidStrategy validStrategy) throws ServiceException {
return this.update(entity, validStrategy, true, false);
}
@Override
public int update(Map entity, ValidStrategy validStrategy, boolean fillUpdateParams,
boolean errorOnUnaffected) throws ServiceException {
if (entity == null || entity.isEmpty()) {
log.debug("Update set fields is empty, the update operation will be skipped.");
return 0;
}
DbConditionConverter converter = jdbc.plugins().getDbConditionConverter();
if (!entity.containsKey("where")) { // 没有where条件, 必须要有主键
if (entity.isEmpty()) {
String details = "NoFieldsThatBeUpdatedWereFound, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_ENTITY_MUST_NOT_BE_EMPTY).setDetails(details);
}
// 查找主键
SimpleFieldColumn pk = sqlHelper().fragment().getPrimaryKey();
if (pk == null) { // 没有找到主键字段
String details = "UnsupportedUpdateById, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_FIELD_IS_UNRESOLVED).setDetails(details);
}
Object value = entity.get(pk.getFieldName());
if (VerifyTools.isBlank(value)) { // 主键值为空
String details = "CanNotExecuteUpdateById, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_VALUE_IS_REQUIRED).setDetails(details);
}
Serializable pkValue;
if (value instanceof Serializable) {
pkValue = (Serializable) value;
} else {
pkValue = value.toString();
}
// 填充实体的修改参数(如修改人修改时间等)
fillEntityUpdateParams(entity, fillUpdateParams);
// 转换为DbUpdate对象
DbUpdate ud = converter.parseMapToDbUpdate(entity);
// 生成主键查询条件
DbWhere where = new DbWhere().on(pk.getFieldName()).equals(pkValue).end();
// 填充Where条件
entityFieldFillExecutor.fillUpdateWhereDataState(where);
entityFieldFillExecutor.fillUpdateWhereParams(where);
return this.doUpdate(ud, where, validStrategy, errorOnUnaffected);
} else { // 如果Update对象中带有where字段, 将where字段值转换为DbWhere对象
Object whereValue = entity.remove("where");
DbWhere where;
if (whereValue == null) {
where = null;
} else if (whereValue instanceof DbWhere) {
where = (DbWhere) whereValue;
} else if (whereValue instanceof Map) {
@SuppressWarnings("unchecked")
Map mapValue = (Map) whereValue;
where = converter.parseMapToDbWhere(mapValue);
} else if (beanClass.isAssignableFrom(whereValue.getClass())) {
@SuppressWarnings("unchecked")
T entityValue = (T) whereValue;
where = converter.convertBeanToDbWhere(entityValue);
} else {
// whereValue只支持DbWhere/map/T
String details = "CanNotExecuteUpdate, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_UNSUPPORTED_WHERE_TYPE).setDetails(details);
}
if (entity.isEmpty()) {
String details = "NoFieldsThatBeUpdatedWereFound, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_ENTITY_MUST_NOT_BE_EMPTY).setDetails(details);
}
// 填充实体的修改参数(如修改人修改时间等)
fillEntityUpdateParams(entity, fillUpdateParams);
// 转换为DbUpdate对象
DbUpdate ud = converter.parseMapToDbUpdate(entity);
// 检查Where条件
DbWhere readyWhere = checkWhere(where);
// 填充Where条件
entityFieldFillExecutor.fillUpdateWhereDataState(where);
entityFieldFillExecutor.fillUpdateWhereParams(where);
return this.doUpdate(ud, readyWhere, validStrategy, errorOnUnaffected);
}
}
@Override
public int update(T entity, DbWhere where) throws ServiceException {
return this.update(entity, where, ValidStrategy.AUTO, true, false);
}
@Override
public int update(T entity, DbWhere where, boolean fillUpdateParams, boolean errorOnUnaffected)
throws ServiceException {
return this.update(entity, where, ValidStrategy.AUTO, fillUpdateParams, errorOnUnaffected);
}
@Override
public int update(T entity, DbWhere where, ValidStrategy validStrategy) throws ServiceException {
return this.update(entity, where, validStrategy, true, false);
}
@Override
public int update(T entity, DbWhere where, ValidStrategy validStrategy, boolean fillUpdateParams,
boolean errorOnUnaffected) throws ServiceException {
if (entity == null) {
log.debug("Update set fields is empty, the update operation will be skipped.");
return 0;
}
Map mapEntity = convertEntityAndFillUpdateParams(entity, fillUpdateParams);
DbConditionConverter converter = jdbc.plugins().getDbConditionConverter();
DbUpdate readyEntity = converter.parseMapToDbUpdate(mapEntity);
if (readyEntity.isEmpty()) {
String details = "NoFieldsThatBeUpdatedWereFound, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_ENTITY_MUST_NOT_BE_EMPTY).setDetails(details);
}
DbWhere readyWhere = checkWhere(where);
entityFieldFillExecutor.fillUpdateWhereDataState(readyWhere);
entityFieldFillExecutor.fillUpdateWhereParams(readyWhere);
return this.doUpdate(readyEntity, readyWhere, validStrategy, errorOnUnaffected);
}
@Override
public int update(DbUpdate entity, DbWhere where) throws ServiceException {
return this.update(entity, where, ValidStrategy.AUTO, true, false);
}
@Override
public int update(DbUpdate entity, DbWhere where, boolean fillUpdateParams, boolean errorOnUnaffected)
throws ServiceException {
return this.update(entity, where, ValidStrategy.AUTO, fillUpdateParams, errorOnUnaffected);
}
@Override
public int update(DbUpdate entity, DbWhere where, ValidStrategy validStrategy) throws ServiceException {
return this.update(entity, where, validStrategy, true, false);
}
@Override
public int update(DbUpdate entity, DbWhere where, ValidStrategy validStrategy, boolean fillUpdateParams,
boolean errorOnUnaffected) throws ServiceException {
if (entity == null || entity.isEmpty()) {
log.debug("Update set fields is empty, the update operation will be skipped.");
return 0;
}
DbWhere readyWhere = checkWhere(where);
entityFieldFillExecutor.fillUpdateWhereDataState(readyWhere);
entityFieldFillExecutor.fillUpdateWhereParams(readyWhere);
// 不需要自动填充修改时的数据状态标记, 没有这样的业务场景
// entityFieldFillExecutor.fillEntityUpdateDataState(entity);
if (fillUpdateParams) {
entityFieldFillExecutor.fillEntityUpdateParams(entity);
}
return this.doUpdate(entity, readyWhere, validStrategy, errorOnUnaffected);
}
protected int doUpdate(DbUpdate readyEntity, DbWhere readyWhere, ValidStrategy validStrategy,
boolean errorOnUnaffected) throws ServiceException {
SqlBuffer buffer = sqlHelper().buildUpdateSql(readyEntity, readyWhere, validStrategy);
int rows;
if (buffer.isBlank()) {
rows = 0;
log.debug("Update set fields is empty, the update operation will be skipped.");
} else {
rows = jdbc.update(buffer);
}
if (rows == 0 && errorOnUnaffected) {
throw new ServiceException(DbErrorCode.DB_AFFECTED_ROWS_IS_ZERO);
}
return rows;
}
@Override
public int updates(List> entities) throws ServiceException {
return updates(entities, ValidStrategy.AUTO, true, this.defaultBatchSize);
}
@Override
public int updates(List> entities, boolean fillUpdateParams) throws ServiceException {
return updates(entities, ValidStrategy.AUTO, fillUpdateParams, this.defaultBatchSize);
}
@Override
public int updates(List> entities, ValidStrategy validStrategy) throws ServiceException {
return updates(entities, validStrategy, true, this.defaultBatchSize);
}
@Override
public int updates(List> entities, ValidStrategy validStrategy, boolean fillUpdateParams)
throws ServiceException {
return updates(entities, validStrategy, fillUpdateParams, this.defaultBatchSize);
}
protected int updates(List> entities, ValidStrategy validStrategy, boolean fillUpdateParams, int batchSize)
throws ServiceException {
VerifyTools.requireNotBlank(entities, "entities");
// 查找主键(批量更新必须要有主键)
SimpleFieldColumn pk = sqlHelper().fragment().getPrimaryKey();
if (pk == null) { // 没有找到主键字段
String details = "UnsupportedBatchUpdate, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_FIELD_IS_UNRESOLVED).setDetails(details);
}
if (entities.size() == 1) {
Object first = entities.get(0);
// 将实体类转换为map, 并执行实体业务数据填充
PkEntity pe = convertAndFillUpdateParams(first, fillUpdateParams);
Serializable pkValue = pe.getPrimaryKey();
if (VerifyTools.isBlank(pkValue)) { // 主键值为空
String details = "UnsupportedBatchUpdate, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_VALUE_IS_REQUIRED).setDetails(details);
}
// 实体类转换为DbUpdate
DbConditionConverter converter = jdbc.plugins().getDbConditionConverter();
DbUpdate ud = converter.parseMapToDbUpdate(pe.getEntity());
// 生成主键限制条件
DbWhere where = new DbWhere().on(pk.getFieldName()).equals(pkValue).end();
// 与批量处理的逻辑保持一致, 不限制数据状态
// entityFieldFillExecutor fillUpdateWhereDataState(where);
// entityFieldFillExecutor fillUpdateWhereParams(where);
return this.doUpdate(ud, where, validStrategy, false);
} else if (batchSize <= 0 || entities.size() <= batchSize) {
return doBatchUpdates(entities, validStrategy, fillUpdateParams);
} else { // 分批导入
List buffer = new ArrayList<>();
int rows = 0;
for (int i = 1, size = entities.size(); i <= size; i++) {
buffer.add(entities.get(i - 1));
if (i % batchSize == 0 || i == size) {
rows += doBatchUpdates(buffer, validStrategy, fillUpdateParams);
buffer.clear();
}
}
return rows;
}
}
/**
* 执行批量更新
*
* @param entities 实体对象列表(只能是entity或map或IdEntity列表, 其他参数将会报错)
* @param validStrategy 校验处理策略
* 注意 : 由于@Column的length/precision/scale有默认值, 一旦启用, 则所有字段都需要覆盖设置!
* @param fillUpdateParams 是否自动填充更新参数(修改人/修改时间等)
* @return 受影响行数
* @throws ServiceException 操作失败
*/
protected int doBatchUpdates(List> entities, ValidStrategy validStrategy, boolean fillUpdateParams)
throws ServiceException {
List contents = new ArrayList<>();
for (Object item : entities) {
// 将实体类转换为map, 并执行实体业务数据填充
PkEntity pkud = convertAndFillUpdateParams(item, fillUpdateParams);
contents.add(pkud);
}
DbVersion version = jdbc.dbVersion();
BatchUpdateExecutor batchOperator = jdbc.plugins().getBatchUpdateExecutor(version);
// 执行批量数据库更新
return batchOperator.updates(contents, validStrategy, jdbc, sqlOperator);
}
@Override
public int logicalDeleteById(Serializable id) throws ServiceException {
VerifyTools.requireNotBlank(id, "id");
return logicalDeleteById(id, true, false);
}
@Override
public int logicalDeleteById(Serializable id, boolean fillUpdateParams, boolean errorOnUnaffected)
throws ServiceException {
VerifyTools.requireNotBlank(id, "id");
SimpleFieldColumn pk = sqlHelper().fragment().getPrimaryKey();
if (pk == null) { // 没有找到主键字段
String details = "UnsupportedDeleteById, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_FIELD_IS_UNRESOLVED).setDetails(details);
}
String primaryField = pk.getFieldName();
DbWhere where = new DbWhere().on(primaryField).equals(id).end();
entityFieldFillExecutor.fillDeleteWhereDataState(where);
entityFieldFillExecutor.fillDeleteWhereParams(where);
return this.doDelete(where, false, fillUpdateParams, errorOnUnaffected);
}
@Override
public int logicalDeleteByIds(Collection extends Serializable> ids) throws ServiceException {
return logicalDeleteByIds(ids, true, false);
}
@Override
public int logicalDeleteByIds(Collection extends Serializable> ids, boolean fillUpdateParams,
boolean errorOnUnaffected) throws ServiceException {
VerifyTools.requireNotBlank(ids, "ids");
SimpleFieldColumn pk = sqlHelper().fragment().getPrimaryKey();
if (pk == null) { // 没有找到主键字段
String details = "UnsupportedDeleteById, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_FIELD_IS_UNRESOLVED).setDetails(details);
}
String primaryField = pk.getFieldName();
DbWhere where = new DbWhere().on(primaryField).in(ids).end();
entityFieldFillExecutor.fillDeleteWhereDataState(where);
entityFieldFillExecutor.fillDeleteWhereParams(where);
return this.doDelete(where, false, fillUpdateParams, errorOnUnaffected);
}
@Override
public int logicalDelete(T where) throws ServiceException {
return logicalDelete(where, true, false);
}
@Override
public int logicalDelete(T where, boolean fillUpdateParams, boolean errorOnUnaffected) throws ServiceException {
if (where == null) {
String details = "If you want to delete all records, please use DbWhere.NONE";
throw new ServiceException(DbErrorCode.DB_WHERE_MUST_NOT_BE_EMPTY).setDetails(details);
}
DbConditionConverter converter = jdbc.plugins().getDbConditionConverter();
DbWhere beanWhere = converter.convertBeanToDbWhere(where);
DbWhere readyWhere = checkWhere(beanWhere);
entityFieldFillExecutor.fillDeleteWhereDataState(readyWhere);
entityFieldFillExecutor.fillDeleteWhereParams(readyWhere);
return this.doDelete(readyWhere, false, fillUpdateParams, errorOnUnaffected);
}
@Override
public int logicalDelete(DbWhere where) throws ServiceException {
return logicalDelete(where, true, false);
}
@Override
public int logicalDelete(DbWhere where, boolean fillUpdateParams, boolean errorOnUnaffected)
throws ServiceException {
DbWhere readyWhere = checkWhere(where);
entityFieldFillExecutor.fillDeleteWhereDataState(readyWhere);
entityFieldFillExecutor.fillDeleteWhereParams(readyWhere);
return this.doDelete(readyWhere, false, fillUpdateParams, errorOnUnaffected);
}
@Override
public int physicalDeleteById(Serializable id) throws ServiceException {
return physicalDeleteById(id, false);
}
@Override
public int physicalDeleteById(Serializable id, boolean errorOnUnaffected) throws ServiceException {
VerifyTools.requireNotBlank(id, "id");
SimpleFieldColumn pk = sqlHelper().fragment().getPrimaryKey();
if (pk == null) { // 没有找到主键字段
String details = "UnsupportedDeleteById, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_FIELD_IS_UNRESOLVED).setDetails(details);
}
String primaryField = pk.getFieldName();
DbWhere where = new DbWhere().on(primaryField).equals(id).end();
return this.doDelete(where, true, false, errorOnUnaffected);
}
@Override
public int physicalDeleteByIds(Collection extends Serializable> ids) throws ServiceException {
return physicalDeleteByIds(ids, false);
}
@Override
public int physicalDeleteByIds(Collection extends Serializable> ids, boolean errorOnUnaffected)
throws ServiceException {
VerifyTools.requireNotBlank(ids, "ids");
SimpleFieldColumn pk = sqlHelper().fragment().getPrimaryKey();
if (pk == null) { // 没有找到主键字段
String details = "UnsupportedDeleteById, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_FIELD_IS_UNRESOLVED).setDetails(details);
}
String primaryField = pk.getFieldName();
DbWhere where = new DbWhere().on(primaryField).in(ids).end();
return this.doDelete(where, true, false, errorOnUnaffected);
}
@Override
public int physicalDelete(T where) throws ServiceException {
return physicalDelete(where, false);
}
@Override
public int physicalDelete(T where, boolean errorOnUnaffected) throws ServiceException {
if (where == null) {
String details = "If you want to delete all records, please use DbWhere.NONE";
throw new ServiceException(DbErrorCode.DB_WHERE_MUST_NOT_BE_EMPTY).setDetails(details);
}
DbConditionConverter converter = jdbc.plugins().getDbConditionConverter();
DbWhere beanWhere = converter.convertBeanToDbWhere(where);
DbWhere readyWhere = checkWhere(beanWhere);
return this.doDelete(readyWhere, true, false, errorOnUnaffected);
}
@Override
public int physicalDelete(DbWhere where) throws ServiceException {
return this.doDelete(where, true, false, false);
}
@Override
public int physicalDelete(DbWhere where, boolean errorOnUnaffected) throws ServiceException {
return this.doDelete(where, true, false, errorOnUnaffected);
}
protected int doDelete(DbWhere readyWhere, boolean physical, boolean fillUpdateParams, boolean errorOnUnaffected)
throws ServiceException {
int rows;
if (physical) { // 物理删除
SqlBuffer buffer = sqlHelper().buildDeleteSql(readyWhere);
rows = jdbc.delete(buffer);
} else { // 逻辑删除
if (entityFieldFillExecutor.supportedTableLogicalDelete()) { // 支持逻辑删除
DbUpdate ud = new DbUpdate();
entityFieldFillExecutor.fillLogicalDeleteDataState(ud);
if (fillUpdateParams) {
entityFieldFillExecutor.fillLogicalDeleteParams(ud);
}
SqlBuffer buffer = sqlHelper().buildUpdateSql(ud, readyWhere, ValidStrategy.AUTO);
if (buffer.isBlank()) {
rows = 0;
log.debug("Update set fields is empty, the logical delete operation will be skipped.");
} else {
rows = jdbc.update(buffer);
}
} else { // 不支持逻辑删除
String details = "UnsupportedLogicDelete, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_UNSUPPORTED_LOGICAL_DELETE).setDetails(details);
}
}
if (rows == 0 && errorOnUnaffected) {
throw new ServiceException(DbErrorCode.DB_AFFECTED_ROWS_IS_ZERO);
}
return rows;
}
/**
* 执行实体业务数据转换及创建参数填充
* 作为以下两个方法的入口, 参数只支持map和T两种:
* fillEntityCreateParams(Map, boolean)/convertEntityAndFillCreateParams(T, boolean)
*
* @param object 实体对象, 只支持map和T两种
* @param fillCreateParams 是否自动填充创建参数
* @return 实体类转换后的map和自动填充的主键ID
*/
protected PkEntity convertAndFillCreateParams(Object object, boolean fillCreateParams) {
if (object == null) {
String details = "CanNotExecuteCreate, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_ENTITY_MUST_NOT_BE_EMPTY).setDetails(details);
}
if (object instanceof PkEntity) {
PkEntity pe = (PkEntity) object;
Map entity = pe.getEntity();
SimpleFieldColumn pk = sqlHelper().fragment().getPrimaryKey();
// 如果PkEntity里面的id不为空, 设置到entity中
if (pk != null && VerifyTools.isNotBlank(pe.getPrimaryKey())) {
entity.put(pk.getFieldName(), pe.getPrimaryKey());
}
if (entity.isEmpty()) {
String details = "NoFieldsThatBeInsertedWereFound, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_ENTITY_MUST_NOT_BE_EMPTY).setDetails(details);
}
// 填充主键/数据状态/创建人/创建时间等信息
fillEntityCreateParams(entity, fillCreateParams);
return pe;
} else if (object instanceof Map) {
@SuppressWarnings("unchecked")
Map entity = (Map) object;
if (entity.isEmpty()) {
String details = "NoFieldsThatBeInsertedWereFound, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_ENTITY_MUST_NOT_BE_EMPTY).setDetails(details);
}
String id = fillEntityCreateParams(entity, fillCreateParams);
return new PkEntity(id, entity);
} else if (beanClass.isAssignableFrom(object.getClass())) {
@SuppressWarnings("unchecked")
T entity = (T) object;
return convertEntityAndFillCreateParams(entity, fillCreateParams);
} else {
String details = "CanNotExecuteCreate, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_UNSUPPORTED_ENTITY_TYPE).setDetails(details);
}
}
/**
* 执行实体业务数据创建参数填充
* 1. 查找主键ID, 如果有主键字段且字段值为空, 就自动生成ID
* 2. 填充创建参数中的数据状态
* 3. 如果fillCreateParams=true, 则填充其他创建参数
*
* @param entity 实体对象
* @param fillCreateParams 是否自动填充创建参数
* @return 填充或获取的主键ID
*/
protected String fillEntityCreateParams(Map entity, boolean fillCreateParams) {
String tableName = sqlHelper().fragment().getTableName();
// 查找主键
String id;
SimpleFieldColumn pk = sqlHelper().fragment().getPrimaryKey();
if (pk == null) {
id = null;
} else if (VerifyTools.isNotBlank(entity.get(pk.getFieldName()))) {
Object pkValue = SqlTools.unwrapDbVariable(entity.get(pk.getFieldName()));
id = pkValue.toString();
} else {
// 生成主键
entity.put(pk.getFieldName(), id = entityFieldFillExecutor.generatePrimaryKeyCode(tableName));
}
entityFieldFillExecutor.fillEntityCreateDataState(entity);
if (fillCreateParams) {
entityFieldFillExecutor.fillEntityCreateParams(entity);
}
return id;
}
/**
* 执行实体业务数据转换及创建参数填充
* 这里存在一个问题, 执行fillEntityCreateParams之后, 入参entity中的字段得不到更新
* 因此, 执行fillEntityCreateParams之前先记录下所有字段值原值
* 执行完fillEntityCreateParams之后比对字段差异, 将差异部分设置回入参entity中
* 比对差异是为了提升性能, 因为对entity操作需要用到反射, 而比对差异只是对map操作, 快很多
* 例如一个类有20个字段, fillEntityCreateParams只修改了2个, 比对差异可以避免对其他18个字段的反射操作
*
* @param entity 实体对象
* @param fillCreateParams 是否自动填充创建参数
* @return 实体类转换后的map和自动填充的主键ID
*/
protected PkEntity convertEntityAndFillCreateParams(T entity, boolean fillCreateParams) {
// 将对象转换为map
DbConditionConverter conditionConverter = jdbc.plugins().getDbConditionConverter();
Map readyEntity = conditionConverter.convertBeanToInsertMap(entity);
if (readyEntity.isEmpty()) {
String details = "NoFieldsThatBeInsertedWereFound, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_ENTITY_MUST_NOT_BE_EMPTY).setDetails(details);
}
// 记录下所有字段值原值, 用于比较差异
Map original = new HashMap<>(readyEntity);
// 填充主键/数据状态/创建人/创建时间等信息
String id = fillEntityCreateParams(readyEntity, fillCreateParams);
// 比对修改后的字段值与原值的差异, 复制到原对象
Map diff = copmareMapDifference(original, readyEntity);
MapToBeanConverter mapToBeanConverter = jdbc.plugins().getMapToBeanConverter();
mapToBeanConverter.fillTo(diff, entity);
return new PkEntity(id, readyEntity);
}
/**
* 执行实体业务数据转换及更新参数填充
*
* @param object 实体对象, 只支持map/T/PkEntity, 其他类型将会报错
* 如果object是map, map中不能有where, 如果有,调这个方法之前要移除, 否则将会报错
* @param fillUpdateParams 是否自动填充更新参数
* @return 转换后的update和where
*/
protected PkEntity convertAndFillUpdateParams(Object object, boolean fillUpdateParams) {
if (object == null) {
String details = "CanNotExecuteUpdate, EntityIsNull, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_ENTITY_MUST_NOT_BE_EMPTY).setDetails(details);
}
// 查找主键
SimpleFieldColumn pk = sqlHelper().fragment().getPrimaryKey();
if (pk == null) { // 没有找到主键字段
String details = "UnsupportedBatchUpdate, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_FIELD_IS_UNRESOLVED).setDetails(details);
}
if (object instanceof PkEntity) {
PkEntity pe = (PkEntity) object;
Serializable pkValue = pe.getPrimaryKey();
// 主键值不能为空
if (VerifyTools.isBlank(pkValue)) { // 主键值为空
String details = "CanNotExecuteUpdateById, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_VALUE_IS_REQUIRED).setDetails(details);
}
Map entity = pe.getEntity();
// 检查UpdateEntity
checkUpdateEntity(entity);
// 填充实体的修改参数(如修改人修改时间等)
fillEntityUpdateParams(entity, fillUpdateParams);
return pe;
} else if (object instanceof Map) {
@SuppressWarnings("unchecked")
Map entity = (Map) object;
// 检查UpdateEntity
checkUpdateEntity(entity);
Object pkValue = entity.get(pk.getFieldName());
// 主键值不能为空
if (VerifyTools.isBlank(pkValue)) { // 主键值为空
String details = "CanNotExecuteUpdateById, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_VALUE_IS_REQUIRED).setDetails(details);
}
// 填充实体的修改参数(如修改人修改时间等)
fillEntityUpdateParams(entity, fillUpdateParams);
return new PkEntity(SqlTools.unwrapDbVariable(pkValue).toString(), entity);
} else if (beanClass.isAssignableFrom(object.getClass())) {
@SuppressWarnings("unchecked")
T entity = (T) object;
Map map = convertEntityAndFillUpdateParams(entity, fillUpdateParams);
Object pkValue = map.get(pk.getFieldName());
// 主键值不能为空
if (VerifyTools.isBlank(pkValue)) { // 主键值为空
String details = "CanNotExecuteUpdateById, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_PRIMARY_KEY_VALUE_IS_REQUIRED).setDetails(details);
}
return new PkEntity(pkValue.toString(), map);
} else {
String details = "CanNotExecuteUpdate, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_UNSUPPORTED_ENTITY_TYPE).setDetails(details);
}
}
private void checkUpdateEntity(Map entity) {
if (entity == null || entity.isEmpty()) {
String details = "NoFieldsThatBeUpdatedWereFound, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_ENTITY_MUST_NOT_BE_EMPTY).setDetails(details);
}
if (entity.containsKey("where")) {
// entity里面不能有where, 如果有,调这个方法之前要移除, 否则将会报错
// 因为批量更新的语法不支持每个ID带有不同的where条件
String details = "Unsupported entity.where";
throw new ServiceException(ResultCode.PARAMETER_VALUE_ERROR).setDetails(details);
}
}
/**
* 执行实体业务数据更新参数填充
*
* @param entity 实体对象
* @param fillUpdateParams 是否自动填充创建参数
*/
protected void fillEntityUpdateParams(Map entity, boolean fillUpdateParams) {
// 不需要自动填充修改时的数据状态标记, 没有这样的业务场景
// entityFieldFillExecutor.fillEntityUpdateDataState(entity);
if (fillUpdateParams) { // 填充单表修改参数(如修改人修改时间等)
entityFieldFillExecutor.fillEntityUpdateParams(entity);
}
}
/**
* 执行实体业务数据更新参数填充
*
* @param ud 待更新的内容
* @param fillUpdateParams 是否自动填充创建参数
*/
protected void fillEntityUpdateParams(DbUpdate ud, boolean fillUpdateParams) {
// 不需要自动填充修改时的数据状态标记, 没有这样的业务场景
// entityFieldFillExecutor.fillEntityUpdateDataState(ud);
if (fillUpdateParams) { // 填充单表修改参数(如修改人修改时间等)
entityFieldFillExecutor.fillEntityUpdateParams(ud);
}
}
/**
* 执行实体业务数据创建参数填充
* 这里存在一个问题, 执行fillEntityUpdateParams之后, 入参entity中的字段得不到更新
* 因此, 执行fillEntityUpdateParams之前先记录下所有字段值原值
* 执行完fillEntityUpdateParams之后比对字段差异, 将差异部分设置回入参entity中
* 比对差异是为了提升性能, 因为对entity操作需要用到反射, 而比对差异只是对map操作, 快很多
* 例如一个类有20个字段, fillEntityUpdateParams只修改了2个, 比对差异可以避免对其他18个字段的反射操作
*
* @param entity 实体对象
* @param fillUpdateParams 是否自动填充更新参数
* @return 实体类转换后的map
*/
protected Map convertEntityAndFillUpdateParams(T entity, boolean fillUpdateParams) {
// 将对象转换为map
DbConditionConverter conditionConverter = jdbc.plugins().getDbConditionConverter();
Map readyEntity = conditionConverter.convertBeanToUpdateMap(entity);
if (readyEntity.isEmpty()) {
String details = "NoFieldsThatBeUpdatedWereFound, class=" + beanClass.getName();
throw new ServiceException(DbErrorCode.DB_ENTITY_MUST_NOT_BE_EMPTY).setDetails(details);
}
// 记录下所有字段值原值, 用于比较差异
Map original = new HashMap<>(readyEntity);
// 填充主键/数据状态/创建人/创建时间等信息
fillEntityUpdateParams(readyEntity, fillUpdateParams);
// 比对修改后的字段值与原值的差异, 复制到原对象
Map diff = copmareMapDifference(original, readyEntity);
MapToBeanConverter mapToBeanConverter = jdbc.plugins().getMapToBeanConverter();
mapToBeanConverter.fillTo(diff, entity);
return readyEntity;
}
/** 获取当前实例的Bean类型 **/
@Override
public Class getBeanClass() {
return beanClass;
}
/** 批量执行时的大小限制(0为无限制) **/
protected int getDefaultBatchSize() {
return defaultBatchSize;
}
/** 批量执行时的大小限制(0为无限制) **/
protected void setDefaultBatchSize(int batchSize) {
this.defaultBatchSize = batchSize;
}
private static class CrudSqlOperator implements SqlOperator {
private final SqlBoot sqlBoot;
private final CrudSqlHelper sqlHelper;
public CrudSqlOperator(Class> beanClass, SqlBoot sqlBoot) {
this.sqlBoot = sqlBoot;
this.sqlHelper = sqlBoot.sqlHelper(beanClass);
}
@Override
public SqlBuffer newSqlBuffer() {
return sqlBoot.newSqlBuffer();
}
@Override
public SqlBuilder newSqlBuilder() {
return sqlBoot.newSqlBuilder();
}
@Override
public ParseTools parseTools() {
return sqlBoot.parseTools();
}
@Override
public CommonSqlTools sqlTools() {
return sqlBoot.sqlTools();
}
@Override
public CrudSqlHelper sqlHelper() {
return sqlHelper;
}
@Override
public SqlFragmentContainer sqlContainer() {
return sqlBoot.sqlContainer();
}
@Override
public SqlDialect sqlDialect() {
return sqlBoot.sqlDialect();
}
@Override
public DbPluginHelper plugins() {
return sqlBoot.plugins();
}
}
}