package top.fastsql.dao; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.util.StringUtils; import top.fastsql.SQL; import top.fastsql.SQLFactory; import top.fastsql.dto.BatchUpdateResult; import top.fastsql.dto.KeyHolderResult; import top.fastsql.dto.ResultPage; import top.fastsql.util.EntityRefelectUtils; import top.fastsql.util.StringExtUtils; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static top.fastsql.util.StringExtUtils.camelToUnderline; /** * 基础DAO 提供CRUD等操作 * * @author 陈佳志 */ @SuppressWarnings({"ALL"}) public abstract class BaseDAO<E, ID> { protected Class<E> entityClass; protected Class<ID> idClass; protected Logger log; protected String className; protected String tableName; /** * 实体类的元数据 */ protected Field idField; protected String idColumnName; protected List<Field> fieldsWithoutId = new ArrayList<>(); protected List<String> columnNamesWithoutId = new ArrayList<>(); protected List<Field> fields = new ArrayList<>(); protected List<String> columnNames = new ArrayList<>(); /** * 所有字段 */ protected String columns = null; /** * save/update/delete 拦截器 配置 */ protected boolean useBeforeInsert = false; protected boolean useAfterInsert = true; protected boolean useBeforeUpdate = false; protected boolean useAfterUpdate = true; protected boolean useBeforeDelete = false; protected boolean useAfterDelete = true; /** * 执行引擎 */ protected SQLFactory sqlFactory; public SQLFactory getSqlFactory() { if (sqlFactory == null) { throw new IllegalArgumentException("sqlFactory is null in BaseDAO,please set it."); } return sqlFactory; } public SQL getSQL() { if (sqlFactory == null) { throw new IllegalArgumentException("sqlFactory is null in BaseDAO,please set it."); } return sqlFactory.createSQL(); } @Autowired public void setSqlFactory(SQLFactory sqlFactory) { this.sqlFactory = sqlFactory; } public BaseDAO() { initMetaData(); } public BaseDAO(SQLFactory sqlFactory) { this.sqlFactory = sqlFactory; initMetaData(); } /** * 初始化DAO元数据 */ @SuppressWarnings({"unchecked", "rawtypes"}) protected void initMetaData() { Type type = getClass().getGenericSuperclass(); if (type instanceof ParameterizedType) { this.entityClass = (Class<E>) ((ParameterizedType) type).getActualTypeArguments()[0]; this.idClass = (Class<ID>) ((ParameterizedType) type).getActualTypeArguments()[1]; } else { this.entityClass = null; } //日志器 this.log = LoggerFactory.getLogger(entityClass); this.className = entityClass.getSimpleName(); this.tableName = EntityRefelectUtils.getTableNameFromEntityClass(this.entityClass); //TODO 现在反射了两次 需要重写为一次 //没有主键 this.fieldsWithoutId = EntityRefelectUtils.getAllFieldWithoutIdByClass(entityClass); this.fieldsWithoutId.forEach(field -> this.columnNamesWithoutId.add(camelToUnderline(field.getName()))); //主键 this.idField = EntityRefelectUtils.getIdField(entityClass); //TODO 2 this.idColumnName = camelToUnderline(idField.getName()); //所有 this.fields.addAll(this.fieldsWithoutId); this.fields.add(0, this.idField); this.columnNames.addAll(this.columnNamesWithoutId); this.columnNames.add(0, camelToUnderline(this.idField.getName())); //所有字段 StringBuilder sb = new StringBuilder(idColumnName); columnNamesWithoutId.forEach(c -> sb.append(',').append(c)); columns = sb.toString(); } /////////////////////////////////////////////////保存方法//////////////////////////////////////// /** * 插入对象中非null的值到数据库 * * @param entity 实体类对象 * @return 插入成功的数量 */ public int insertSelective(E entity) { if (useBeforeInsert) { beforeInsert(entity); } //SQL语句部分字符串构建器 StringBuilder nameBuilder = new StringBuilder(); StringBuilder valueBuilder = new StringBuilder(); //遍历 fields.stream() .filter(field -> EntityRefelectUtils.getFieldValue(entity, field) != null) .forEach(field -> { nameBuilder.append(",").append(StringExtUtils.camelToUnderline(field.getName())); valueBuilder.append(",:").append(field.getName()); }); //构建SQL实例 SQL sql = getSQL() .INSERT_INTO(tableName, nameBuilder.deleteCharAt(0).toString()) .VALUES(valueBuilder.delete(0, 1).toString()) .beanParameter(entity); int count = sql.update(); if (useAfterInsert) { afterInsert(entity, count); } //返回修改行数 return count; } /** * 插入对象中的值到数据库,null值在数据库中会设置为NULL */ public int insert(E entity) { if (useBeforeInsert) { beforeInsert(entity); } StringBuilder nameBuilder = new StringBuilder(); StringBuilder valueBuilder = new StringBuilder(); fields.forEach(field -> { nameBuilder.append(",").append(StringExtUtils.camelToUnderline(field.getName())); valueBuilder.append(",:").append(field.getName()); }); SQL sql = getSQL() .INSERT_INTO(tableName, nameBuilder.deleteCharAt(0).toString()) .VALUES(valueBuilder.deleteCharAt(0).toString()) .beanParameter(entity); int count = sql.update(); if (useAfterInsert) { afterInsert(entity, count); } return count; } public KeyHolderResult insertForKey(E entity, String... keyColumns) { if (useBeforeInsert) { beforeInsert(entity); } StringBuilder nameBuilder = new StringBuilder(); StringBuilder valueBuilder = new StringBuilder(); Object fieldValue = EntityRefelectUtils.getFieldValue(entity, idField); if (fieldValue == null) { fieldsWithoutId.forEach(field -> { nameBuilder.append(",").append(StringExtUtils.camelToUnderline(field.getName())); valueBuilder.append(",:").append(field.getName()); }); } else { fields.forEach(field -> { nameBuilder.append(",").append(StringExtUtils.camelToUnderline(field.getName())); valueBuilder.append(",:").append(field.getName()); }); } SQL sql = getSQL() .INSERT_INTO(tableName, nameBuilder.deleteCharAt(0).toString()) .VALUES(valueBuilder.deleteCharAt(0).toString()) .beanParameter(entity); KeyHolderResult keyHolderResult = sql.updateForKey(keyColumns); if (useAfterInsert) { afterInsert(entity, keyHolderResult.getCount()); } return keyHolderResult; } public KeyHolderResult insertForId(E entity) { if (useBeforeInsert) { beforeInsert(entity); } StringBuilder nameBuilder = new StringBuilder(); StringBuilder valueBuilder = new StringBuilder(); Object fieldValue = EntityRefelectUtils.getFieldValue(entity, idField); if (fieldValue == null) { fieldsWithoutId.forEach(field -> { nameBuilder.append(",").append(StringExtUtils.camelToUnderline(field.getName())); valueBuilder.append(",:").append(field.getName()); }); } else { fields.forEach(field -> { nameBuilder.append(",").append(StringExtUtils.camelToUnderline(field.getName())); valueBuilder.append(",:").append(field.getName()); }); } SQL sql = getSQL() .INSERT_INTO(tableName, nameBuilder.deleteCharAt(0).toString()) .VALUES(valueBuilder.deleteCharAt(0).toString()) .beanParameter(entity); KeyHolderResult keyHolderResult = sql.updateForKey(idColumnName); if (useAfterInsert) { afterInsert(entity, keyHolderResult.getCount()); } return keyHolderResult; } /** * 批量插入 */ public int[] batchInsert(List<E> entities) { StringBuilder nameBuilder = new StringBuilder(); StringBuilder valueBuilder = new StringBuilder(); fields.forEach(field -> { nameBuilder.append(",").append(StringExtUtils.camelToUnderline(field.getName())); valueBuilder.append(",:").append(field.getName()); }); String sql = getSQL() .INSERT_INTO(tableName, nameBuilder.deleteCharAt(0).toString()) .VALUES(valueBuilder.deleteCharAt(0).toString()).build(); SqlParameterSource[] sqlParameterSources = new BeanPropertySqlParameterSource[entities.size()]; for (int i = 0; i < sqlParameterSources.length; i++) { sqlParameterSources[i] = new BeanPropertySqlParameterSource(entities.get(i)); } return getSQL().getNamedParameterJdbcTemplate().batchUpdate(sql, sqlParameterSources); } /////////////////////////////修改 ///////////////////////////////////////////// /** * 全更新 null值在 数据库中设置为null */ public int update(E entity) { if (useBeforeUpdate) { beforeUpdate(entity); } //TODO ID id = (ID) EntityRefelectUtils.getFieldValue(entity, idField); if (StringUtils.isEmpty(id)) { throw new RuntimeException("修改时对象id不能为空"); } StringBuilder sqlBuilder = new StringBuilder(); fieldsWithoutId.forEach(field -> sqlBuilder.append("," + StringExtUtils.camelToUnderline(field.getName()) + "=:" + field.getName()) ); SQL sql = getSQL() .UPDATE(tableName) .SET(sqlBuilder.deleteCharAt(0).toString()) .WHERE(idColumnName + "=:" + idColumnName) .beanParameter(entity); int count = sql.update(); if (useAfterUpdate) { afterUpdate(entity, count); } return count; } public int insertOrUpdate(E entity) { ID id = (ID) EntityRefelectUtils.getFieldValue(entity, idField); if (StringUtils.isEmpty(id)) { //插入 return insert(entity); } else { //更新 E row = selectOneById(id); if (row == null) { return insert(entity); } else { return update(entity); } } } /** * 仅更新非null, null值 不更新 */ public int updateSelective(E entity) { if (useBeforeUpdate) { beforeUpdate(entity); } ID id = (ID) EntityRefelectUtils.getFieldValue(entity, idField); if (StringUtils.isEmpty(id)) { throw new RuntimeException("修改时对象id不能为空"); } StringBuilder sqlBuilder = new StringBuilder(); fieldsWithoutId.forEach(field -> sqlBuilder.append("," + StringExtUtils.camelToUnderline(field.getName()) + "=:" + field.getName()) ); SQL sql = getSQL() .UPDATE(tableName) .SET(sqlBuilder.deleteCharAt(0).toString()) .WHERE(idColumnName + "=:" + idColumnName) .beanParameter(entity); int count = sql.update(); if (useAfterUpdate) { afterUpdate(entity, count); } return count; } public int updateColumns(E entity, String... columns) { ID id = (ID) EntityRefelectUtils.getFieldValue(entity, idField); if (StringUtils.isEmpty(id)) { throw new RuntimeException("修改时对象id不能为空"); } StringBuilder sqlBuilder = new StringBuilder(); for (String column : columns) { sqlBuilder.append("," + column + "=:" + EntityRefelectUtils.underlineToCamelFirstLower(column)); } SQL sql = getSQL() .UPDATE(tableName) .SET(sqlBuilder.deleteCharAt(0).toString()) .WHERE(idColumnName + "=:" + idColumnName) .beanParameter(entity); if (useBeforeUpdate) { beforeUpdate(entity); } int count = sql.update(); if (useAfterUpdate) { afterUpdate(entity, count); } return count; } public int updateSetWhere(String set, String where, String... params) { return getSQL().useSql("UPDATE " + tableName + " SET " + set + " WHERE " + where).varParameter(params).update(); } public int updateSet(String set, String... params) { return getSQL().useSql("UPDATE " + tableName + " SET " + set).varParameter(params).update(); } /////////////////////////////////////////////////删除方法//////////////////////////////////////// /** * 根据id删除数据 */ public int deleteOneById(ID id) { if (useBeforeDelete) { beforeDelete(id); } //String sql = "DELETE FROM " + tableName + " WHERE " + idColumnName + " = ?"; SQL sql = getSQL() .DELETE_FROM(tableName) .WHERE(idColumnName + "=:" + idColumnName) .mapItemsParameter("id", id); int count = sql.update(); if (useAfterDelete) { afterDelete(id, count); } return count; } /** * 删除所有数据 */ public int deleteAll() { return getSQL().useSql("DELETE FROM " + tableName).update(); } /** * 根据条件删除 */ public int deleteWhere(String sqlCondition, Object... values) { String sql = "DELETE FROM " + tableName + " WHERE " + sqlCondition; return getSQL().useSql(sql).varParameter(values).update(); } /** * 根据id列表批量删除数据 */ public BatchUpdateResult deleteInBatch(List<ID> ids) { String sql = "DELETE FROM " + tableName + " WHERE " + idColumnName + "=:" + idColumnName; List<Map<String, Object>> mapList = new ArrayList<>(ids.size()); for (ID id : ids) { Map<String, Object> map = new HashMap<>(); map.put(idColumnName, id); mapList.add(map); } return getSQL().useSql(sql).batchUpdateByMapParams(mapList); } //////////////////////////////find one///////////////////////////////////// /** * 通过id查找 */ public E selectOneById(ID id) { E returnObject; try { returnObject = getSQL() .SELECT(columns) .FROM(tableName) .WHERE(idColumnName + "=:" + idColumnName) .mapItemsParameter(idColumnName, id) .queryOne(entityClass); } catch (EmptyResultDataAccessException e) { returnObject = null; } return returnObject; } /** * 通过entity查找,不为空的值将会作为where条件 */ public E selectOneByEntity(E entity) { String clause = " 1=1 "; for (Field field : fields) { Object fieldValue = EntityRefelectUtils.getFieldValue(entity, field); if (!StringUtils.isEmpty(fieldValue)){ clause+=" AND "+StringExtUtils.camelToUnderline(field.getName())+" = :"+field.getName(); } } E returnObject; try { returnObject = getSQL() .SELECT(columns) .FROM(tableName) .WHERE(clause) .parameter(new BeanPropertySqlParameterSource(entity)) .queryOne(entityClass); } catch (EmptyResultDataAccessException e) { returnObject = null; } return returnObject; } /** * 通过where条件查找一条记录 * 查找姓名为1年龄大于23的记录 selectOneWhere("name=? and age 大于号 ?", "wang",23) * * @param sqlCondition name=:1 and age=:2 * @param values "wang",23 */ public E selectOneWhere(String sqlCondition, Object... values) { //sql String sql = "SELECT " + columns + " FROM " + tableName + " WHERE " + sqlCondition; List<E> dataList = getSqlFactory().createSQL().useSql(sql) .varParameter(values) .queryList(new BeanPropertyRowMapper<>(entityClass)); if (dataList.isEmpty()) { return null; } else if (dataList.size() == 1) { return dataList.get(0); } else { log.error(tableName + "#findOneWhere()返回多条数据"); throw new RuntimeException(tableName + "#findOneWhere()返回多条数据"); } } public E selectOneWhere(String sqlCondition, SqlParameterSource parameterSource) { //sql String sql = "SELECT " + columns + " FROM " + tableName + " WHERE " + sqlCondition; List<E> dataList = getSqlFactory().createSQL().useSql(sql) .parameter(parameterSource) .queryList(new BeanPropertyRowMapper<>(entityClass)); if (dataList.size() == 0) { return null; } else if (dataList.size() == 1) { return dataList.get(0); } else { log.error(tableName + "#findOneWhere()返回多条数据"); throw new RuntimeException(tableName + "#findOneWhere()返回多条数据"); } } //////////////////////////////find list///////////////////////////////////// public List<E> selectAll() { return getSQL().SELECT(columns).FROM(tableName).queryList(entityClass); } public List<E> selectWhere(String sqlCondition, Object... values) { //sql String sql = "SELECT " + columns + " FROM " + tableName + " WHERE " + sqlCondition; return getSQL().useSql(sql).varParameter(values).queryList(new BeanPropertyRowMapper<>(entityClass)); } public List<E> selectWhere(String sqlCondition, SqlParameterSource parameterSource) { //sql String sql = "SELECT " + columns + " FROM " + tableName + " WHERE " + sqlCondition; return getSQL().useSql(sql).parameter(parameterSource).queryList(new BeanPropertyRowMapper<>(entityClass)); } public List<E> selectByEntity(E entity) { String clause = " 1=1 "; for (Field field : fields) { Object fieldValue = EntityRefelectUtils.getFieldValue(entity, field); if (!StringUtils.isEmpty(fieldValue)){ clause+=" AND "+StringExtUtils.camelToUnderline(field.getName())+" = :"+field.getName(); } } return getSQL().SELECT(columns) .FROM(tableName) .WHERE(clause) .parameter(new BeanPropertySqlParameterSource(entity)) .queryList(entityClass); } ////////////////////////////////////count/////////////////////////////////////////// public int countWhere(String sqlCondition, Object... values) { String sql = "SELECT count(*) FROM " + tableName + " WHERE " + sqlCondition; return getSQL().useSql(sql).varParameter(values).queryInteger(); } public int countWhere(String sqlCondition, SqlParameterSource parameterSource) { //sql String sql = "SELECT count(*) FROM " + tableName + " WHERE " + sqlCondition; return getSQL().useSql(sql).parameter(parameterSource).queryInteger(); } public int count() { return getSQL().SELECT("COUNT(*)").FROM(tableName).queryInteger(); } //////////////////////////////////query page/////////////////////////////////////////////////////////////// public ResultPage<E> selectPageWhere(String sqlCondition, int pageNumber, int perPage, Object... values) { //sql String sql = "SELECT " + columns + " FROM " + tableName + " WHERE " + sqlCondition; return getSQL().useSql(sql).varParameter(values) .queryPage(pageNumber, perPage, new BeanPropertyRowMapper<>(entityClass)); } public ResultPage<E> selectPageWhere(String sqlCondition, int pageNumber, int perPage, SqlParameterSource parameterSource) { String sql = "SELECT " + columns + " FROM " + tableName + " WHERE 1=1 AND " + sqlCondition; return getSQL().useSql(sql).parameter(parameterSource) .queryPage(pageNumber, perPage, new BeanPropertyRowMapper<>(entityClass)); } public ResultPage<E> selectPage(int pageNumber, int perPage) { String sql = "SELECT " + columns + " FROM " + tableName; return getSQL().useSql(sql) .queryPage(pageNumber, perPage, new BeanPropertyRowMapper<>(entityClass)); } ////////////////////////////////////拦截器/////////////////////////// protected void beforeInsert(E entity) { } protected void afterInsert(E entity, int count) { if (count < 1) { log.warn(this.entityClass.getSimpleName() + "插入成功数量" + count + ",entity=" + entity.toString()); } } protected void beforeUpdate(E entity) { } protected void afterUpdate(E entity, int count) { if (count < 1) { log.warn(this.entityClass.getSimpleName() + "更新成功数量" + count + ",entity=" + entity.toString()); } } protected void beforeDelete(ID id) { } protected void afterDelete(ID id, int count) { if (count < 1) { log.warn(this.entityClass.getSimpleName() + "删除成功数量" + count + ",id=" + id); } } }