package com.lunhan.xxx.repository; import com.lunhan.xxx.common.ConstantFactory; import com.lunhan.xxx.common.PagerResult; import com.lunhan.xxx.common.config.SysConfig; import com.lunhan.xxx.common.enums.ELogger; import com.lunhan.xxx.common.enums.EResultCode; import com.lunhan.xxx.common.exceptions.BusinessException; import com.lunhan.xxx.common.orm2.SqlBuilder; import com.lunhan.xxx.common.orm2.enums.ColumnBasic; import com.lunhan.xxx.common.orm2.models.SqlCondition; import com.lunhan.xxx.common.orm2.models.SqlParameter; import com.lunhan.xxx.common.util.*; import com.lunhan.xxx.repository.columns.ETestInfo; import org.apache.commons.lang3.BooleanUtils; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementCreator; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; import org.springframework.transaction.annotation.Transactional; import javax.persistence.Column; import javax.persistence.Id; import javax.persistence.Table; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.sql.*; import java.util.*; import java.util.stream.Collectors; /** * 数据访问 实现类 * * @param 数据实体 */ public class BasicDao { @Autowired protected JdbcTemplate db; private Class clazz; private String tableName; private ColumnBasic[] columns; protected List listColumnsName; protected String allColumnsStr; protected static final Logger logger = LoggerUtil.get(ELogger.SQL_LOG); protected static final Logger sysLogger = LoggerUtil.get(ELogger.SYS_ERROR); /** * 构造方法 * * @param columns 数据实体对应的所有列枚举 */ public BasicDao(ColumnBasic[] columns) { this.clazz = (Class) ( (ParameterizedType) getClass().getGenericSuperclass() ).getActualTypeArguments()[0]; this.columns = columns; this.listColumnsName = Arrays.stream(columns).map(ColumnBasic::getColumnName).collect(Collectors.toList()); this.allColumnsStr = StringUtil.join(listColumnsName, ","); Table annotation = clazz.getAnnotation(Table.class); if (null == annotation) { return; } this.tableName = annotation.name(); } /** * 获取数据实体class类型 * * @return 数据实体class类型 */ public Class getClazz() { return clazz; } /** * 获取数据实体对应的所有列枚举 * * @return 数据实体对应的所有列枚举 */ public ColumnBasic[] getColumns() { return columns; } /** * 获取数据库表名 * * @return 数据库表名 */ public String getTableName() { return tableName; } /** * 根据条件获取数据实体列表(不传条件,默认只获取前500条数据) * * @return 数据实体列表 */ @Transactional(readOnly = true) protected List getList(SqlBuilder... builder) { StringBuilder sbSql = new StringBuilder(String.format("SELECT %s FROM %s", allColumnsStr, tableName)); Object[] params = new Object[0]; int[] paramTypes = new int[0]; if (builder.length == 1) { SqlCondition condition = builder[0].build(); String where = condition.getSql(); List listParam = condition.getParamList(); params = new Object[listParam.size()]; paramTypes = new int[listParam.size()]; for (int i = 0; i < listParam.size(); i++) { SqlParameter parameter = listParam.get(i); params[i] = parameter.getValue(); paramTypes[i] = parameter.getType(); } if (StringUtil.isNotNullOrEmpty(where) && BooleanUtils.isFalse(where.contains("WHERE"))) { sbSql.append(" WHERE "); } sbSql.append(where); } sbSql.append(";"); String sql = sbSql.toString(); if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + StringUtil.join(Arrays.stream(params).map(Object::toString).collect(Collectors.toList()), ConstantFactory.SQL_STR_COMMA) + "]"); } List> list = db.queryForList(sql, params, paramTypes); if (ListUtil.isNullOrEmpty(list)) { return new ArrayList<>(); } List result = new ArrayList<>(); Field[] fields = clazz.getDeclaredFields(); for (Map row : list) { T item = this.fillEntity(fields, row); if (Objects.isNull(item)) { continue; } result.add(item); } return result; } /** * 根据主键获取数据实体 * * @param id 主键id * @return 数据实体 */ @Transactional(readOnly = true) public T getById(Long id) { try { String sql = String.format("SELECT %s FROM %s WHERE id=?", allColumnsStr, tableName); if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + id + "(LONG)" + "]"); } Map row = db.queryForMap(sql, new Object[]{id}, new int[]{Types.BIGINT}); return this.fillEntity(clazz.getDeclaredFields(), row); } catch (EmptyResultDataAccessException e) { return null; } catch (Exception e) { logger.error("BasicDao.get(Long id)发生异常", e); throw new BusinessException(EResultCode.ERROR, "BasicDao.get(Long id)发生异常." + e.getMessage()); } } /** * 条件查询单个数据实体 * * @param builder * @return */ @Transactional(readOnly = true) protected T get(SqlBuilder builder) { try { builder.from(tableName); StringBuilder sbSql = new StringBuilder(); SqlCondition conditionFull = builder.build(); String sqlFull = conditionFull.getSql(); if (BooleanUtils.isFalse(sqlFull.contains("SELECT"))) { sbSql.append("SELECT "); sbSql.append(allColumnsStr); } sbSql.append(sqlFull); List listParam = conditionFull.getParamList(); Object[] params = new Object[listParam.size()]; int[] paramTypes = new int[listParam.size()]; for (int i = 0; i < listParam.size(); i++) { SqlParameter parameter = listParam.get(i); params[i] = parameter.getValue(); paramTypes[i] = parameter.getType(); } sbSql.append(";"); String sql = sbSql.toString(); if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + StringUtil.join(Arrays.stream(params).map(Object::toString).collect(Collectors.toList()), ConstantFactory.SQL_STR_COMMA) + "]"); } Map row = db.queryForMap(sql, params, paramTypes); return this.fillEntity(clazz.getDeclaredFields(), row); } catch (EmptyResultDataAccessException e) { logger.error("BasicDao.get(SqlBuilder builder)", e); return null; } catch (Exception e) { logger.error("BasicDao.get(SqlBuilder builder)发生异常", e); throw new BusinessException(EResultCode.ERROR, "BasicDao.get(SqlBuilder builder)发生异常." + e.getMessage()); } } /** * 根据传入sql查询数据 * * @param sql * @return */ public List> getSql(String sql) { List> list = db.queryForList(sql); return list; } public Map querySql(String sql){ Map stringObjectMap = db.queryForMap(sql); return stringObjectMap; } /** * 根据传入sql查询数据 * * @param builder sql语句构建器 */ public List> getSql(SqlBuilder builder) { SqlCondition conditionFull = builder.build(); String sql = conditionFull.getSql(); List listParam = conditionFull.getParamList(); Object[] params = new Object[listParam.size()]; int[] paramTypes = new int[listParam.size()]; for (int i = 0; i < listParam.size(); i++) { SqlParameter parameter = listParam.get(i); params[i] = parameter.getValue(); paramTypes[i] = parameter.getType(); } List> list = db.queryForList(sql, params, paramTypes); return list; } /** * 查询总数 * * @param sql * @return */ public Integer getCount(String sql) { return db.queryForObject(sql, Integer.class); } /** * 根据条件获取数据实体列表(不传条件,默认只获取前500条数据) * * @return 数据实体列表 */ @Transactional(readOnly = true) protected PagerResult getPageList(SqlBuilder builder) { builder.from(tableName); StringBuilder sbSql = new StringBuilder(); Integer pageSize = builder.getPageSize(); Integer pageIndex = builder.getPageIndex(); SqlCondition conditionFull = builder.build(); String sqlFull = conditionFull.getSql(); if (BooleanUtils.isFalse(sqlFull.contains("SELECT"))) { sbSql.append("SELECT "); sbSql.append(allColumnsStr); } sbSql.append(sqlFull); List listParam = conditionFull.getParamList(); Object[] params = new Object[listParam.size()]; int[] paramTypes = new int[listParam.size()]; for (int i = 0; i < listParam.size(); i++) { SqlParameter parameter = listParam.get(i); params[i] = parameter.getValue(); paramTypes[i] = parameter.getType(); } SqlCondition conditionCount = builder.count(); String sqlCount = conditionCount.getSql(); Integer rowCount = db.queryForObject(sqlCount, params, Integer.class); if (Objects.isNull(rowCount) || rowCount.compareTo(0) < 1) { return new PagerResult<>(pageSize, pageIndex, 0L, new ArrayList<>()); } sbSql.append(";"); String sql = sbSql.toString(); if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + StringUtil.join(Arrays.stream(params).map(Object::toString).collect(Collectors.toList()), ConstantFactory.SQL_STR_COMMA) + "]"); } List> list = db.queryForList(sql, params, paramTypes); if (ListUtil.isNullOrEmpty(list)) { return new PagerResult<>(pageSize, pageIndex, rowCount, new ArrayList<>()); } List result = new ArrayList<>(); Field[] fields = clazz.getDeclaredFields(); for (Map row : list) { T item = this.fillEntity(fields, row); if (Objects.isNull(item)) { continue; } result.add(item); } return new PagerResult<>(pageSize, pageIndex, rowCount, result); } /** * 新增一个数据实体 * * @param model 数据实体对象 * @return 是否成功 */ public Boolean add(T model) { KeyHolder holder = new GeneratedKeyHolder(); int rowCount = db.update(new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { List listValue = new ArrayList<>(); List listCol = new ArrayList<>(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { // 要设置属性可达,不然会抛出IllegalAccessException异常 field.setAccessible(true); Object value = null; try { value = field.get(model); } catch (IllegalAccessException e) { continue; } if (Objects.isNull(value)) { continue; } Column annotation = field.getAnnotation(Column.class); if (Objects.isNull(annotation)) { continue; } if (Objects.equals(Boolean.FALSE, annotation.insertable())) { continue; } Id annotationId = field.getAnnotation(Id.class); if (Objects.nonNull(annotationId)) { continue; } listValue.add(value); listCol.add(annotation.name()); } if (ListUtil.isNullOrEmpty(listValue)) { throw new RuntimeException("At BasicDao.add, there is no data be insert.The model json: " + SerializeUtil.toJson(model)); } String insertColumns = StringUtil.join(listCol, ","); String valuesPlaceholder = StringUtil.join(listValue.stream().map(c -> "?").collect(Collectors.toList())); String sql = String.format("INSERT INTO %s(%s) VALUES(%s);", tableName, insertColumns, valuesPlaceholder); PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); for (int i = 0; i < listValue.size(); i++) { //setValue(ps, i + 1, listValue.get(i)); ps.setObject(i + 1, listValue.get(i), Types.VARCHAR); } if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + StringUtil.join(listValue.stream().map(c -> c.toString()).collect(Collectors.toList()), ConstantFactory.SQL_STR_COMMA) + "]"); } return ps; } }, holder); if (rowCount > 0) { long id = holder.getKey().longValue(); Field field = null; try { field = clazz.getDeclaredField("id"); } catch (NoSuchFieldException e) { sysLogger.error("BasicDao.add(T model)", e); } if (Objects.nonNull(field)) { try { // 要设置属性可达,不然会抛出IllegalAccessException异常 field.setAccessible(true); field.set(model, id); } catch (IllegalAccessException e) { sysLogger.error("BasicDao.add(T model)", e); } } return Boolean.TRUE; } return Boolean.FALSE; } /** * 新增一个数据实体(主键非自增列) * * @param model 数据实体对象 * @return 是否成功 */ public Boolean addNotIncrement(T model) { List listValue = new ArrayList<>(); List listCol = new ArrayList<>(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { // 要设置属性可达,不然会抛出IllegalAccessException异常 field.setAccessible(true); Object value = null; try { value = field.get(model); } catch (IllegalAccessException e) { continue; } if (Objects.isNull(value)) { continue; } Column annotation = field.getAnnotation(Column.class); if (Objects.isNull(annotation)) { continue; } if (Objects.equals(Boolean.FALSE, annotation.insertable())) { continue; } listValue.add(value); listCol.add(annotation.name()); } if (ListUtil.isNullOrEmpty(listValue)) { throw new RuntimeException("At BasicDao.addNotIncrement, there is no data be insert.The model json: " + SerializeUtil.toJson(model)); } String insertColumns = StringUtil.join(listCol, ","); String valuesPlaceholder = StringUtil.join(listValue.stream().map(c -> "?").collect(Collectors.toList())); String sql = String.format("INSERT INTO %s(%s) VALUES(%s);", tableName, insertColumns, valuesPlaceholder); if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + StringUtil.join(listValue.stream().map(Object::toString).collect(Collectors.toList()), ConstantFactory.SQL_STR_COMMA) + "]"); } try { int rowCount = db.update(sql, listValue.toArray()); if (rowCount > 0) { return Boolean.TRUE; } return Boolean.FALSE; } catch (Exception e) { logger.error("BasicDao.addNotIncrement(T model)", e); return Boolean.FALSE; } } /** * 根据主键id删除数据实体 * * @param id 主键id * @return 是否成功 */ public Boolean remove(Long id) { String sql = String.format("DELETE FROM %s WHERE id=?;", tableName); if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + id + "(LONG)" + "]"); } int rowCount = db.update(sql, id); if (rowCount > 0) { return Boolean.TRUE; } return Boolean.FALSE; } /** * 根据条件删除数据实体 * * @param builder 条件 * @return 是否成功 */ protected Boolean remove(SqlBuilder builder) { SqlCondition build = builder.build(); String where = build.getSql(); List listParam = build.getParamList(); String sql = String.format("DELETE FROM %s %s;", tableName, where); Object[] values = new Object[listParam.size()]; for (int i = 0; i < listParam.size(); i++) { SqlParameter p = listParam.get(i); values[i] = p.getValue(); } if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + Arrays.toString(values) + "]"); } int rowCount = db.update(sql, values); if (rowCount > 0) { return Boolean.TRUE; } return Boolean.FALSE; } /** * 根据主键id逻辑删除数据 * * @param id 主键id * @return 是否成功 */ public Boolean deleteLogic(Long id) { String sql = String.format("UPDATE %s SET is_delete=1 WHERE id=?;", tableName); if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + id + "(INTEGER)" + "]"); } int rowCount = db.update(sql, id); if (rowCount > 0) { return Boolean.TRUE; } return Boolean.FALSE; } /** * 根据条件逻辑删除数据 * * @param listId id列表 * @return 是否成功 */ public Boolean deleteLogic(List listId) { SqlCondition build = new SqlBuilder().where(ETestInfo.ID.in(listId)).build(); String where = build.getSql(); List listParam = build.getParamList(); String sql = String.format("UPDATE %s SET is_delete=1 %s;", tableName, where); Object[] values = new Object[listParam.size()]; for (int i = 0; i < listParam.size(); i++) { SqlParameter p = listParam.get(i); values[i] = p.getValue(); } if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + Arrays.toString(values) + "]"); } int rowCount = db.update(sql, values); if (rowCount > 0) { return Boolean.TRUE; } return Boolean.FALSE; } /** * 修改一个数据实体 * * @param model 数据实体对象 * @return 是否成功 */ public Boolean modify(T model) { List listValue = new ArrayList<>(); List listSet = new ArrayList<>(); Field[] fields = clazz.getDeclaredFields(); String idColumnName = ""; Object idValue = null; for (Field field : fields) { // 要设置属性可达,不然会抛出IllegalAccessException异常 field.setAccessible(true); Object value = null; try { value = field.get(model); } catch (IllegalAccessException e) { continue; } if (Objects.isNull(value)) { continue; } Column annotation = field.getAnnotation(Column.class); if (Objects.isNull(annotation)) { continue; } if (Objects.equals(Boolean.FALSE, annotation.updatable())) { continue; } Id annotationId = field.getAnnotation(Id.class); if (Objects.nonNull(annotationId)) { idColumnName = annotation.name(); idValue = value; if (NumericUtil.tryParseLong(idValue).compareTo(0L) < 1) { throw new RuntimeException("At BasicDao.modify, the value of “id” is must.The model json: " + SerializeUtil.toJson(model)); } continue; } listValue.add(value); listSet.add(annotation.name() + "=?"); } if (ListUtil.isNullOrEmpty(listValue)) { throw new RuntimeException("At BasicDao.modify, there is no data be update.The model json: " + SerializeUtil.toJson(model)); } String sql = String.format("UPDATE %s SET %s WHERE %s =?;", tableName, StringUtil.join(listSet, ","), idColumnName); // 添加sql参数 id的值 listValue.add(idValue); if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + StringUtil.join(listValue.stream().map(Object::toString).collect(Collectors.toList()), ConstantFactory.SQL_STR_COMMA) + "]"); } int rowCount = db.update(sql, listValue.toArray()); if (rowCount > 0) { return Boolean.TRUE; } return Boolean.FALSE; } /** * 批量新增数据实体 * * @param list 数据实体对象列表 * @return 是否成功 */ public Boolean addList(List list) { if (ListUtil.isNullOrEmpty(list)) { return Boolean.TRUE; } List listValue = new ArrayList<>(); List listCol = new ArrayList<>(); Field[] fields = clazz.getDeclaredFields(); for (int i = 0; i < list.size(); i++) { T model = list.get(i); List values = new ArrayList<>(); for (int j = 0; j < fields.length; j++) { Field field = fields[j]; // 要设置属性可达,不然会抛出IllegalAccessException异常 field.setAccessible(true); Object value = null; try { value = field.get(model); } catch (IllegalAccessException e) { continue; } if (Objects.isNull(value)) { continue; } Column annotation = field.getAnnotation(Column.class); if (Objects.isNull(annotation)) { continue; } if (Objects.equals(Boolean.FALSE, annotation.insertable())) { continue; } if (0 == i) { listCol.add(annotation.name()); } values.add(value); } listValue.add(values.toArray()); } if (ListUtil.isNullOrEmpty(listCol)) { throw new RuntimeException("At BasicDao.addList, there is no data be update.The list json: " + SerializeUtil.toJson(list)); } String valuesPlaceholder = StringUtil.join(listCol.stream().map(c -> "?").collect(Collectors.toList())); String sql = String.format("INSERT INTO %s(%s) VALUES(%s);", tableName, StringUtil.join(listCol, ","), valuesPlaceholder); if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + StringUtil.join(listValue.stream().map(Object::toString).collect(Collectors.toList()), ConstantFactory.SQL_STR_COMMA) + "]"); } int[] batchUpdate = db.batchUpdate(sql, listValue); if (batchUpdate.length > 0) { return Boolean.TRUE; } return Boolean.FALSE; } /** * 批量新增数据实体 * * @param list 数据实体对象列表 * @return 是否成功 */ public Boolean modifyList(List list) { if (ListUtil.isNullOrEmpty(list)) { return Boolean.TRUE; } List listValue = new ArrayList<>(); List listSet = new ArrayList<>(); Field[] fields = clazz.getDeclaredFields(); for (int i = 0; i < list.size(); i++) { T model = list.get(i); List values = new ArrayList<>(); Field idField = null; for (int j = 0; j < fields.length; j++) { Field field = fields[j]; // 要设置属性可达,不然会抛出IllegalAccessException异常 field.setAccessible(true); Object value = null; try { value = field.get(model); } catch (IllegalAccessException e) { continue; } if (Objects.isNull(value)) { continue; } Column annotation = field.getAnnotation(Column.class); if (Objects.isNull(annotation)) { continue; } if (Objects.equals(Boolean.FALSE, annotation.updatable())) { continue; } Id annotationId = field.getAnnotation(Id.class); if (Objects.nonNull(annotationId)) { idField = field; continue; } if (0 == i) { listSet.add(annotation.name() + "=?"); } values.add(value); } if (Objects.isNull(idField)) { throw new RuntimeException("At BasicDao.modifyList, the value of “id” is must.The model json: " + SerializeUtil.toJson(model)); } try { // 要设置属性可达,不然会抛出IllegalAccessException异常 idField.setAccessible(true); // 设置参数“id”的值 Object id = idField.get(model); if (NumericUtil.tryParseLong(id).compareTo(0L) < 1) { throw new RuntimeException("At BasicDao.modifyList, the value of “id” is must.The model json: " + SerializeUtil.toJson(model)); } values.add(id); } catch (IllegalAccessException e) { sysLogger.error("BasicDao.modifyList", e); } listValue.add(values.toArray()); } if (ListUtil.isNullOrEmpty(listSet)) { throw new RuntimeException("At BasicDao.addList, there is no data be update.The list json: " + SerializeUtil.toJson(list)); } String valuesPlaceholder = StringUtil.join(listSet.stream().map(c -> "?").collect(Collectors.toList())); String sql = String.format("UPDATE %s SET %s WHERE id=?;", tableName, StringUtil.join(listSet, ",")); if (SysConfig.isSqlLog()) { logger.info(sql + "\n[" + StringUtil.join(listValue.stream().map(Object::toString).collect(Collectors.toList()), ConstantFactory.SQL_STR_COMMA) + "]"); } int[] batchUpdate = db.batchUpdate(sql, listValue); if (batchUpdate.length > 0) { return Boolean.TRUE; } return Boolean.FALSE; } /** * 将查询得到的字段键值对封装为数据实体 * * @param fields 数据实体的字段列表 * @param row 查询得到的字段键值对 * @return 数据实体 */ protected T fillEntity(Field[] fields, Map row) { T item = null; try { item = clazz.newInstance(); } catch (Exception e) { sysLogger.error("BasicDao.fillEntity", e); } if (null == item) { return null; } for (Map.Entry column : row.entrySet()) { String columnName = column.getKey(); Field field = Arrays.stream(fields) .filter(c -> { Column annotation = c.getAnnotation(Column.class); if (null == annotation) { return Boolean.FALSE; } return Objects.equals(annotation.name(), columnName); }) .findAny().orElse(null); if (null == field) { continue; } // 要设置属性可达,不然会抛出IllegalAccessException异常 field.setAccessible(true); try { field.set(item, column.getValue()); } catch (IllegalAccessException e) { sysLogger.error("BasicDao.fillEntity(Field[] fields, Map row)", e); } } return item; } /** * 将查询得到的字段键值对封装为数据实体 * * @param clazz 数据实体的class类型 * @param row 查询得到的字段键值对 * @return 数据实体 */ protected M fillEntity(Class clazz, Map row) { M item = null; try { item = clazz.newInstance(); } catch (Exception e) { sysLogger.error("BasicDao.fillEntity", e); } if (null == item) { return null; } Field[] fields = clazz.getDeclaredFields(); for (Map.Entry column : row.entrySet()) { String columnName = column.getKey(); Field field = Arrays.stream(fields) .filter(c -> { Column annotation = c.getAnnotation(Column.class); if (null == annotation) { return Boolean.FALSE; } return Objects.equals(annotation.name(), columnName); }) .findAny().orElse(null); if (null == field) { continue; } // 要设置属性可达,不然会抛出IllegalAccessException异常 field.setAccessible(true); try { field.set(item, column.getValue()); } catch (IllegalAccessException e) { sysLogger.error("BasicDao.fillEntity(Class clazz, Map row)", e); } } return item; } }