package com.yanzuoguang.dao.impl; import com.yanzuoguang.dao.BaseDao; import com.yanzuoguang.dao.DaoConst; import com.yanzuoguang.db.impl.AllBeanRowMapper; import com.yanzuoguang.util.base.ObjectHelper; import com.yanzuoguang.util.exception.CodeException; import com.yanzuoguang.util.helper.DateHelper; import com.yanzuoguang.util.helper.StringHelper; import com.yanzuoguang.util.vo.InitDao; import com.yanzuoguang.util.vo.MapRow; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 数据库操作的基本工具类 * @author 颜佐光 */ public abstract class BaseDaoImpl extends BaseDaoSql implements BaseDao { /** * 获取当前主键 * * @return */ private String getIdentity() { return StringHelper.toString(this.db.queryCell(this.getClass(), "GET_KEY", "SELECT @@IDENTITY")); } /** * 获取主键名称 * * @return 获取主键名称 */ protected String getKey() { if (this.table == null) { throw new CodeException("类" + this.getClass().getName() + "未发现表结构"); } return this.table.getTable().getKeyName(); } /** * 获取主键值 * * @param model 需要获取主键的实体 * @return */ protected String getKeyString(Object model) { String keyField = this.getKey(); Object key = ObjectHelper.get(model, keyField); if (StringHelper.isEmpty(key)) { return ""; } String keyString = key.toString(); if (DaoConst.ZERO .equals(keyString)) { keyString = ""; } return keyString; } /** * 设置主键值 * * @param model 需要设置的实体 * @param key 需要设置的主键值 */ protected void setKeyString(Object model, String key) { String keyField = this.getKey(); ObjectHelper.set(model, keyField, key); } /** * 根据输入参数来获取主键 * * @param from 可以为实体或字符串。为实体时必须包含 主键 字段 或者 id 字段。 * @return */ protected String getInputKey(Object from) { String key; if (from != null && from.getClass() == String.class) { key = StringHelper.toString(from); } else { key = this.getKeyString(from); } if (StringHelper.isEmpty(key)) { key = StringHelper.toString(ObjectHelper.get(from, "id")); } if (StringHelper.isEmpty(key)) { key = ""; } return key; } /** * 创建数据,当不传入了主键时,则会自动生成主键,传入时不会生成。 * * @param model 需要创建的数据 * @return 创建的主键编号, 创建成功,返回主键,否则为空 */ @Override public String create(Object model) { // 判断主键是字符串和需要生成主键 boolean isKeyString = this.table.getTable().getKeyType() == String.class; String keyString = this.getKeyString(model); // 生成主键 if (StringHelper.isEmpty(keyString) && isKeyString) { keyString = StringHelper.getNewID(); this.setKeyString(model, keyString); } // 检测数据合法性 this.check(DaoConst.OPERATOR_TYPE_CREATE, keyString, model); // 执行创建的SQL语句 int ret = updateSql(DaoConst.CREATE, model); // 判断是否需要获取自增编号(主键为整形) if (StringHelper.isEmpty(keyString) && !isKeyString) { keyString = this.getIdentity(); this.setKeyString(model, keyString); } // 最终处理 this.created(model); // 返回执行结果 String retVal = ret > 0 ? keyString : ""; return retVal; } /** * 修改数据 * * @param model 需要修改的数据 * @return 删除的主键编号 */ @Override public String update(Object model) { String keyString = this.getKeyString(model); if (StringHelper.isEmpty(keyString)) { throw new CodeException("表" + this.table.getTable().getName() + "主键值为空时不能更新"); } this.check(DaoConst.OPERATOR_TYPE_UPDATE, keyString, model); SqlData sqlData = this.getSql(DaoConst.UPDATE); int ret = updateSql(sqlData, model); String retVal = ret > 0 ? keyString : ""; return retVal; } /** * 检测数据 * * @param operatorType 操作方法类型 * @param keyString 主键 * @param model 需要检测的数据 */ protected void check(int operatorType, String keyString, Object model) { if (model instanceof InitDao) { InitDao to = (InitDao) model; to.init(); } } /** * 保存数据 * * @param model 需要保存的数据 * @return 保存的主键编号 */ @Override public String save(Object model) { String id = this.getKeyString(model); if (StringHelper.isEmpty(id)) { return create(model); } else { return update(model); } } /** * 删除数据 * * @param model 需要删除的数据 * @return 删除的主键编号 */ @Override public int remove(Object model) { // 获取来源主键 Object from = model; String keyString = getInputKey(from); // 当主键存在值时,直接通过主键删除 if (!StringHelper.isEmpty(keyString)) { // 去掉其他非主键的属性 from = new HashMap<String, Object>(DaoConst.COLLECTION_INIT_SIZE); this.setKeyString(from, keyString); // 调用删除日志 this.check(DaoConst.OPERATOR_TYPE_REMOVE, keyString, from); } else { List<MapRow> rows = this.query(MapRow.class, DaoConst.LOAD, from); for (MapRow row : rows) { keyString = this.getKeyString(from); if (StringHelper.isEmpty(keyString)) { keyString = StringHelper.toString(AllBeanRowMapper.getLoweRowField(row, this.getKey())); } // 调用删除日志 this.check(DaoConst.OPERATOR_TYPE_REMOVE, keyString, row); } } // 调用删除语句 SqlData sqlData = this.getSql(DaoConst.REMOVE); return updateSql(sqlData, from); } /** * 加载数据 * * @param model 加载数据的请求参数 * @param cls 需要加载的数据的类型 * @param <T> 返回数据的类型 * @return 需要返回的数据 */ @Override public <T extends Object> T load(Object model, Class<T> cls) { // 获取来源主键 Object from = model; String key = this.getInputKey(from); // 当主键存在时,只通过主键加载 if (!StringHelper.isEmpty(key)) { from = new HashMap<String, Object>(DaoConst.COLLECTION_INIT_SIZE); this.setKeyString(from, key); } // 通过传入数据进行加载 T to = this.queryFirst(cls, DaoConst.LOAD, from); if (to == null) { return to; } // 判断来源主键是否存在,不存在则获取加载后的主键 if (StringHelper.isEmpty(key)) { key = this.getKeyString(to); } check(DaoConst.OPERATOR_TYPE_LOAD, key, to); return to; } /** * 添加统计数据 * * @param cls 类型 * @param model 实体 * @param <T> 泛型类型 * @return 增加统计的数据编号 */ public <T extends Object> String addGroup(Class<T> cls, T model) { // 判断前台实体 if (model == null) { return ""; } // 获取前台分组的MD5标识 String md5 = this.getMd5(DaoConst.GROUP_QUERY, model); if (!StringHelper.isEmpty(this.table.getTable().getMD5KeyName())) { ObjectHelper.set(model, this.table.getTable().getMD5KeyName(), md5); } // 获取标识的实体 T from; if (this.table.getTable().getKeyType() == String.class) { from = model; this.setKeyString(model, md5); } else if (!StringHelper.isEmpty(this.table.getTable().getMD5KeyName())) { Map<String, Object> map = new HashMap<>(DaoConst.COLLECTION_INIT_SIZE); map.put(this.table.getTable().getMD5KeyName(), md5); from = this.load(map, cls); } else { from = this.queryFirst(cls, DaoConst.GROUP_QUERY, model); } // 当没有存在,则创建,否则 UpdateAdd if (from == null) { return this.create(model); } else { // 获取后台的编号,并写入到前台传入的数据上面 String keyField = this.getKey(); Object key = ObjectHelper.get(from, keyField); ObjectHelper.set(model, keyField, key); // 执行更新SQL语句 SqlData sqlData = this.getSql(DaoConst.GROUP_ADD); int ret = this.updateSql(sqlData, model); if (ret < 1) { return this.create(model); } else { return key.toString(); } } } /** * 根据SQL语句名称和实体获取MD5值 * * @param sqlName SQL语句名称 * @param model 获取加密之后的实体 * @param <T> 获取的类型 * @return 获取加密之后的值 */ protected <T extends Object> String getMd5(String sqlName, T model) { SqlData sql = this.getSql(sqlName); StringBuilder sb = new StringBuilder(); String date = StringHelper.EMPTY; for (SqlDataField field : sql.getSqlDataFields()) { if (sb.length() > 0) { sb.append(":"); } Object item = ObjectHelper.get(model, field.paraName); sb.append(item); if (StringHelper.isEmpty(date)) { String itemString = String.valueOf(item); if (item instanceof Date) { date = DateHelper.getDateTimeString((Date) item); } else if (DateHelper.isDateFormat(itemString)) { date = itemString; } } } if (StringHelper.isEmpty(date)) { return StringHelper.md5(sb.toString()); } else { return StringHelper.getNewMD5Id(DateHelper.getDateTime(date), sb.toString()); } } /** * 添加统计数据列表 * * @param sqlName 需要执行的SQL语句名称 * @param model 需要执行的SQL语句的实体 * @return */ protected int addGroupList(String sqlName, Object model) { this.updateSql(sqlName + "_GroupInit", model); return this.updateSql(sqlName + "_GroupAdd", model); } /*** * 查询数据是否存在,当存在时修改,否则增加 * @param cls 需要创建的实体的类型 * @param sqlName 执行的SQL语句 * @param request 前台参数,不能包含主键以及其他不需要修改的字段 * @return 保存成功,返回保存的ID,保存失败,返回空值 */ public <T extends Object> String saveWith(Class<T> cls, String sqlName, Object request) { T from = this.queryFirst(cls, sqlName, request); if (from == null) { try { from = cls.newInstance(); } catch (Exception ex) { throw new CodeException("创建对象" + cls.getName() + "出错", ex); } ObjectHelper.writeWithFrom(from, request); return this.create(from); } else { ObjectHelper.writeWithFrom(from, request); return this.update(from); } } /** * 创建成功后的处理 * * @param model 创建的实体数据 */ protected void created(Object model) { } /** * 执行是否存在的SQL语句 * * @param sqlName SQL语句名称 * @param model 实体 * @param msg 消息 */ protected void checkExist(String sqlName, Object model, String msg) { MapRow row = this.queryFirst(sqlName, model); if (row != null) { throw new CodeException(msg); } } }