Commit c5d2b285 authored by yanzg's avatar yanzg

处理数据类

parent f018bc85
package com.yanzuoguang.code;
/**
* 加密算法生成接口
*/
public interface CodePwd {
/**
* 获取算法的名称
*
* @return
*/
String getName();
/**
* 生成二维码
*
* @param rand 随机数
* @param day 日期
* @param index 序号
* @param pwd 密码
* @return 生成的结果
*/
String getCode(String rand, String day, String index, String pwd);
}
package com.yanzuoguang.code;
/**
* 加密算法0版实现
*/
public class CodePwdImpl implements CodePwd {
/**
* 当前算法的名称
*
* @return
*/
@Override
public String getName() {
/**
* 颜佐光的第一个版本的算法
*/
return "Yanzuoguang.Zero";
}
/**
* 生成二维码
*
* @param rand 随机数
* @param day 日期
* @param index 序号
* @param pwd 密码
* @return 生成的结果
*/
@Override
public String getCode(String rand, String day, String index, String pwd) {
String ret = "";
// 1. 将随即数和天数进行组合生成字符串
String randDay = "";
{
int randSize = rand.length();
int daySize = day.length();
int maxLen = Math.max(rand.length(), day.length());
for (int i = 0; i < maxLen; i++) {
if (i < daySize) {
randDay += day.charAt(i);
}
if (i < randSize) {
randDay += rand.charAt(i);
}
}
}
// 2. 将组合后的数字进行交换
int randDaySize = randDay.length();
char[] dayChars = new char[randDaySize];
{
for (int i = 0; i < randDaySize; i++) {
dayChars[i] = randDay.charAt(i);
}
for (int i = 0; i < randDaySize / 2; i++) {
if (i % 2 == 0) {
int to = randDaySize - i - 1;
dayChars[to] = randDay.charAt(i);
dayChars[i] = randDay.charAt(to);
}
}
for (int i = 0; i < randDaySize; i++) {
ret += dayChars[i];
}
}
// 3.a 将随机数和后面的序号组成新的字符串
String codePwd = index;
// 3.b 将新的字符串加上密码进行处理
int newSize = codePwd.length();
int pwdSize = pwd.length();
int[] newValue = new int[newSize];
// 3.c 转换为具体的数字,并且加上密码
for (int i = 0; i < newSize; i++) {
int from = Integer.parseInt("" + codePwd.charAt(i));
int pwdIndex = i % pwdSize;
int to = Integer.parseInt("" + pwd.charAt(pwdIndex));
int val = (from + to);
newValue[i] = val;
}
// 根据最后一位数字进行相加
int last = newValue[newSize - 1];
for (int i = 0; i < newSize - 1; i++) {
int flag = 1;
if (last % 2 == 0) {
flag = -flag;
}
if (newValue[i] % 2 == 0) {
flag = -flag;
}
if (i % 2 == 0) {
flag = -flag;
}
newValue[i] += flag * last;
}
// 往后移动5位
int movePos = newSize / 2;
int[] toVals = new int[newSize];
for (int i = 0; i < newSize; i++) {
int j = i - movePos;
if (j < 0) {
j = newSize + j;
}
toVals[i] = newValue[j];
}
newValue = toVals;
for (int i = 0; i < newSize; i++) {
newValue[i] = (newValue[i] % 10 + 10) % 10;
ret += newValue[i];
}
return ret;
}
// public static void main(String[] args) {
// int[] pos2 = {3, 4, 5, 6, 8};
// int startPos = 0;
// int endPos = 1000000;
//
// Date start = new Date();
// CodePwdReplaceImpl item = new CodePwdReplaceImpl();
// Map<String, Integer> map = new HashMap<>();
// for (int i = startPos; i < endPos; i++) {
// String index = String.format("%09d", i);
// String code = item.getCode("", "", index, "18532354168");
// if (map.containsKey(code)) {
// map.put(code, map.get(code) + 1);
// System.err.println("code: " + map.get(code));
// } else {
// map.put(code, 1);
// }
// int rand2 = pos2[new Random().nextInt(pos2.length)];
// String mobile = "1" + rand2 + code;
// System.out.println(mobile);
// }
// Date end = new Date();
// System.out.println("长度: " + (endPos - startPos) + " time:" + (end.getTime() - start.getTime()));
// }
}
package com.yanzuoguang.dao;
/**
* 数据基本操作接口
* created by yanzu on 2017/5/30.
*/
public interface BaseDao {
/**
* 创建数据,当不传入了主键时,则会自动生成主键,传入时不会生成。
*
* @param model 需要创建的数据
* @return 创建的主键编号
*/
String create(Object model);
/**
* 修改数据
*
* @param model 需要修改的数据
* @return 删除的主键编号
*/
String update(Object model);
/**
* 保存数据,有主键时修改,无主键时创建
*
* @param model 需要保存的数据
* @return 保存的主键编号
*/
String save(Object model);
/**
* 删除数据
*
* @param model 需要删除的数据
* @return 删除的主键编号
*/
String remove(Object model);
/**
* 加载数据
*
* @param model 加载数据的请求参数
* @param cls 需要加载的数据的类型
* @param <T> 返回数据的类型
* @return 需要返回的数据
*/
<T extends Object> T load(Object model, Class<T> cls);
}
package com.yanzuoguang.dao;
/**
* created by yanzu on 2017/5/30.
*/
public class DaoConst {
public static final int OperatorTypeCreate = 0;
public static final int OperatorTypeUpdate = 1;
public static final int OperatorTypeRemove = 2;
public static final int OperatorTypeLoad = 3;
/**
* 创建
*/
public static final String Create = "create";
/**
* 修改
*/
public static final String Update = "update";
/**
* 删除
*/
public static final String Remove = "remove";
/**
* 加载
*/
public static final String Load = "load";
/**
* 查询
*/
public static final String Query = "query";
/**
* GROUP增加数据的SQL语句
*/
public static final String GroupAdd = "GroupAdd";
/**
* GROUP查询数据的SQL语句
*/
public static final String GroupQuery = "GroupQuery";
}
package com.yanzuoguang.dao.Impl;
import com.yanzuoguang.dao.BaseDao;
import com.yanzuoguang.dao.DaoConst;
import com.yanzuoguang.util.exception.CodeException;
import com.yanzuoguang.util.helper.StringHelper;
import com.yanzuoguang.util.obj.ObjectHelper;
import com.yanzuoguang.util.vo.InitDao;
import java.util.HashMap;
import java.util.Map;
/**
* 数据库操作的基本工具类
* created by yanzu on 2017/5/30.
*/
public abstract class BaseDaoImpl extends BaseDaoSql implements BaseDao {
/**
* 获取当前主键
*
* @return
*/
private String getIdentity() {
return StringHelper.toString(this.db.queryCell("SELECT @@IDENTITY"));
}
/**
* 获取主键名称
*
* @return 获取主键名称
*/
protected String getKey() {
if (this.Table == null) {
throw new CodeException("类" + this.getClass().getName() + "未发现表结构");
}
return this.Table.Table.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 ("0".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 创建的主键编号, 创建成功,返回主键,否则为空
*/
public String create(Object model) {
// 判断主键是字符串和需要生成主键
boolean isKeyString = this.Table.Table.getKeyType() == String.class;
String keyString = this.getKeyString(model);
// 生成主键
if (StringHelper.isEmpty(keyString) && isKeyString) {
keyString = StringHelper.getNewID();
this.setKeyString(model, keyString);
}
// 检测数据合法性
this.check(DaoConst.OperatorTypeCreate, 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 删除的主键编号
*/
public String update(Object model) {
String keyString = this.getKeyString(model);
if (StringHelper.isEmpty(keyString)) {
throw new CodeException("表" + this.Table.Table.getName() + "主键值为空时不能更新");
}
this.check(DaoConst.OperatorTypeUpdate, 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 保存的主键编号
*/
public String save(Object model) {
String id = this.getKeyString(model);
if (StringHelper.isEmpty(id)) {
return create(model);
} else {
return update(model);
}
}
/**
* 删除数据
*
* @param model 需要删除的数据
* @return 删除的主键编号
*/
public String remove(Object model) {
Object from = model;
// 获取来源主键
String keyString = getInputKey(from);
if (StringHelper.isEmpty(keyString)) {
MapRow to = new MapRow();
ObjectHelper.writeWithFrom(to, model);
from = this.queryFirst(MapRow.class, DaoConst.Load, from);
if (from == null) {
return "";
}
keyString = this.getKeyString(from);
}
// 当主键存在时,只通过主键加载
if (!StringHelper.isEmpty(keyString)) {
from = new HashMap<String, Object>();
this.setKeyString(from, keyString);
}
this.check(DaoConst.OperatorTypeRemove, keyString, from);
SqlData sqlData = this.getSql(DaoConst.Remove);
int ret = updateSql(sqlData, from);
String retVal = ret > 0 ? keyString : "";
return retVal;
}
/**
* 加载数据
*
* @param model 加载数据的请求参数
* @param cls 需要加载的数据的类型
* @param <T> 返回数据的类型
* @return 需要返回的数据
*/
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>();
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.OperatorTypeLoad, 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.GroupQuery, model);
if (!StringHelper.isEmpty(this.Table.Table.getMD5KeyName())) {
ObjectHelper.set(model, this.Table.Table.getMD5KeyName(), md5);
}
// 获取标识的实体
T from;
if (this.Table.Table.getKeyType() == String.class) {
from = model;
this.setKeyString(model, md5);
} else if (!StringHelper.isEmpty(this.Table.Table.getMD5KeyName())) {
Map<String, Object> map = new HashMap<String, Object>();
map.put(this.Table.Table.getMD5KeyName(), md5);
from = this.load(map, cls);
} else {
from = this.queryFirst(cls, DaoConst.GroupQuery, 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.GroupAdd);
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();
for (SqlDataField field : sql.sqlDataFields) {
if (sb.length() > 0) {
sb.append(":");
}
Object item = ObjectHelper.get(model, field.paraName);
sb.append(item);
}
return StringHelper.md5(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);
}
}
}
package com.yanzuoguang.dao.Impl;
import com.yanzuoguang.dao.TableAnnotation;
import com.yanzuoguang.db.DbExecute;
import com.yanzuoguang.util.cache.MemoryCache;
import com.yanzuoguang.util.exception.CodeException;
import com.yanzuoguang.util.helper.StringHelper;
import com.yanzuoguang.util.obj.ObjectHelper;
import com.yanzuoguang.util.vo.PageSizeData;
import com.yanzuoguang.util.vo.PageSizeReq;
import com.yanzuoguang.util.vo.PageSizeReqVo;
import javax.annotation.Resource;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* SQL语句基本操作类
*/
public abstract class BaseDaoSql {
/**
* 定义列表记录缓存对象
*/
protected MemoryCache cacheList = new MemoryCache(0);
/**
* 数据库执行类
*/
@Resource
protected DbExecute db;
/**
* 当前Dao的表结构SQL语句信息
*/
protected TableSqlCache Table = null;
/**
* 缓存的表结构和SQL语句
*/
protected static MemoryCache<TableSqlCache> Cache = new MemoryCache<>();
/**
* 获取数据库执行类
*
* @return
*/
protected DbExecute getDb() {
return db;
}
/**
* 构造函数
*/
public BaseDaoSql() {
this.initTable();
}
/**
* 初始化当前类对应的SQL语句对象
*/
private void initTable() {
String cls = this.getClass().getName();
// 外检测,防止锁影响性能
this.Table = Cache.get(cls);
// 判断是否已经取到对象
if (this.Table == null) {
this.Table = new TableSqlCache();
Cache.put(cls, this.Table);
this.init();
}
}
/**
* 注册SQL语句
*/
protected abstract void init();
/**
* 注册表结构,会根据实体以及表名自动创建Create、update、remove、Load等SQL语句
*
* @param clsModel 操作的实体,主键放在第一位,其他字段放到后面;需要注意的是必需和表结构对应起来,会有隐性BUG,比如说在实体中增加了字段,会导致增加修改失败
* @return 当前的表结构
*/
protected TableSqlCache register(Class<?> clsModel) {
TableAnnotation annotation = clsModel.getAnnotation(TableAnnotation.class);
if (annotation == null) {
throw new CodeException("该页面未绑定表");
}
return this.register(annotation.value(), clsModel);
}
/**
* 注册表结构,会根据实体以及表名自动创建Create、update、remove、Load等SQL语句
*
* @param tableName 表名,数据库中的表名
* @param clsModel 操作的实体,主键放在第一位,其他字段放到后面;需要注意的是必需和表结构对应起来,会有隐性BUG,比如说在实体中增加了字段,会导致增加修改失败
* @return 当前的表结构
*/
protected TableSqlCache register(String tableName, Class<?> clsModel) {
// 生成表结构
TableStruct table = new TableStruct(tableName, clsModel);
// 根据表结构生成基本的SQL语句
table.init(this.Table);
return this.Table;
}
/**
* 获取SQL语句
*
* @param name 需要获取的SQL语句的名称
* @return 对应名称的SQL语句
*/
protected SqlData getSql(String name) {
return getSql(name, true);
}
/**
* 获取SQL语句
*
* @param name 需要获取的SQL语句的名称
* @return 对应名称的SQL语句
*/
protected SqlData getSql(String name, boolean isThrow) {
if (this.Table == null) {
throw new CodeException("类" + this.getClass().getName() + "未发现表结构");
}
SqlData sql = this.Table.Sqls.get(name);
if (isThrow && sql == null) {
throw new CodeException("类" + this.getClass().getName() + "未发现SQL语句" + name);
}
return sql;
}
/**
* 当更新数据时
*/
protected void onUpdateSql(Object model) {
// 删除所有查询的缓存
cacheList.clear();
}
/**
* 执行更新语句
*
* @param sqlData
* @param model
* @return
*/
protected int updateSql(SqlData sqlData, Object model) {
List<Object> paras = new ArrayList<Object>();
String sql = this.getQueryPara(paras, sqlData, model);
int ret = db.update(sql, paras.toArray());
this.onUpdateSql(model);
return ret;
}
/**
* 更新SQL语句
*
* @param sqlName 参数对应的名称
* @param model 参数对应的实体
* @return 修改成功,返回修改条数,否则为0
*/
public int updateSql(String sqlName, Object model) {
SqlData sqlData = this.getSql(sqlName);
int ret = updateSql(sqlData, model);
return ret;
}
/**
* 根据SQL语句信息查询第一个单元格
*
* @param sqlData SQL语句信息
* @param model 前台参数
* @return 查询的结果
*/
protected Object queryCell(SqlData sqlData, Object model) {
List<Object> paras = new ArrayList<Object>();
String sql = this.getQueryPara(paras, sqlData, model);
Object cell = this.queryCellWithCache(sql, paras.toArray());
return cell;
}
/**
* 根据SQL名称获取第一个单元格
*
* @param sqlName
* @param model
* @return
*/
protected Object queryCell(String sqlName, Object model) {
return this.queryCell(this.getSql(sqlName), model);
}
/**
* 根据SQL语句信息查询数据
*
* @param cls 数据结果类型
* @param sqlData SQL语句信息
* @param model 前台参数
* @param <T> 返回数据类型
* @return 查询的结果
*/
protected <T extends Object> List<T> queryData(Class<T> cls, SqlData sqlData, Object model) {
List<Object> paras = new ArrayList<Object>();
String sql = this.getQueryPara(paras, sqlData, model);
List<T> list = this.queryWithCache(cls, sql, paras.toArray());
return list;
}
/**
* 查询不分页数据
*
* @param cls 数据结果类型
* @param sqlName SQL语句名称
* @param model 前台参数
* @param <T> 返回数据类型
* @return 查询的结果
*/
protected <T extends Object> List<T> query(Class<T> cls, String sqlName, Object model) {
SqlData sqlData = this.getSql(sqlName);
return queryData(cls, sqlData, model);
}
/**
* 查询第一条数据
*
* @param cls 数据结果类型
* @param sqlName SQL语句名称
* @param model 前台参数
* @param <T> 返回数据类型
* @return 查询的结果
*/
protected <T extends Object> T queryFirst(Class<T> cls, String sqlName, Object model) {
PageSizeReq pageSize = new PageSizeReqVo();
pageSize.setPageIndex(1);
pageSize.setPageSize(1);
List<T> list = this.queryPageData(cls, pageSize, sqlName, model);
T retVal = list.size() > 0 ? list.get(0) : null;
return retVal;
}
/**
* 查询分页数据,仅仅只是查询分页中的数据,不查询分页信息。如:包含的总数据数量
*
* @param cls 数据结果类型
* @param pageSize 分页参数
* @param sqlName SQL语句名称
* @param model 前台参数
* @param <T> 返回数据类型
* @return 查询的结果
*/
protected <T extends Object> List<T> queryPageData(Class<T> cls, PageSizeReq pageSize, String sqlName, Object model) {
SqlData from = this.getSql(sqlName);
// 对SQL语句进行分页处理
SqlData to = from.copy();
to.Sql = from.Sql;
to.addCode("{LIMIT}", " LIMIT " + pageSize.getPageStart() + "," + pageSize.getPageSize());
return queryData(cls, to, model);
}
/**
* 查询分页数据,仅仅只是查询分页中的数据。如:包含的总数据数量
*
* @param cls 数据结果类型
* @param pageSize 分页参数
* @param sqlName SQL语句名称
* @param model 前台参数
* @param <T> 返回数据类型
* @return 查询的结果
*/
protected <T extends Object> PageSizeData<T> queryPage(Class<T> cls, PageSizeReqVo pageSize, String sqlName, Object model) {
// 获取需要执行的SQL语句
SqlData from = this.getSql(sqlName);
// 设置基本参数值
PageSizeData<T> data = new PageSizeData<T>();
data.setPageIndex(pageSize.getPageIndex());
data.setPageSize(pageSize.getPageSize());
// 对SQL语句进行分页处理
SqlData to = from.copy();
to.addCode("{LIMIT}", " LIMIT " + pageSize.getPageStart() + "," + pageSize.getPageSize());
// 按照分页查询数据
List<Object> paras = new ArrayList<Object>();
String sql = this.getQueryPara(paras, to, model);
// 查询实体数据
List<T> list = this.queryWithCache(cls, sql, paras.toArray());
data.setList(list);
// 查询分页总条数的SQL语句
String sqlTo = sql;
// 获取分页查询的SQL语句
SqlData fromPageSize = getSql(sqlName + TableSqlCache.PAGE_SIZE_TAG, false);
if (fromPageSize != null) {
sqlTo = getQueryPara(new ArrayList<>(), fromPageSize, model);
}
// 查询总数据量
String sqlSize = "SELECT COUNT(1) FROM (" +
sqlTo.replaceAll("(?i)(ORDER\\s+BY\\s+[^)]+){0,1}(limit\\s+\\d+,\\d+\\s*){0,1}$", "")
+ ") t";
data.setPageTotal(StringHelper.toInt(queryCellWithCache(sqlSize, paras.toArray())));
return data;
}
/**
* 根据SQL语句信息查询数据
*
* @param sqlData SQL语句信息
* @param model 前台参数
* @return 查询的结果
*/
protected List<MapRow> queryData(SqlData sqlData, Object model) {
return this.queryData(MapRow.class, sqlData, model);
}
/**
* 查询不分页数据
*
* @param sqlName SQL语句名称
* @param model 前台参数
* @return 查询的结果
*/
protected List<MapRow> query(String sqlName, Object model) {
return this.query(MapRow.class, sqlName, model);
}
/**
* 查询第一条数据
*
* @param sqlName SQL语句名称
* @param model 前台参数
* @return 查询的结果
*/
protected MapRow queryFirst(String sqlName, Object model) {
return this.queryFirst(MapRow.class, sqlName, model);
}
/**
* 查询分页数据,仅仅只是查询分页中的数据,不查询分页信息。如:包含的总数据数量
*
* @param pageSize 分页参数
* @param sqlName SQL语句名称
* @param model 前台参数
* @return 查询的结果
*/
protected List<MapRow> queryPageData(PageSizeReqVo pageSize, String sqlName, Object model) {
return this.queryPageData(MapRow.class, pageSize, sqlName, model);
}
/**
* 查询分页数据,仅仅只是查询分页中的数据,不查询分页信息。如:包含的总数据数量
*
* @param pageSize 分页参数
* @param sqlName SQL语句名称
* @param model 前台参数
* @return 查询的结果
*/
protected PageSizeData<MapRow> queryPage(PageSizeReqVo pageSize, String sqlName, Object model) {
return this.queryPage(MapRow.class, pageSize, sqlName, model);
}
/**
* 获取SQL语句的参数
*
* @param paras SQL语句
* @param sqlData SQL语句的参数
* @param model 参数的实体
* @return SQL条件
*/
protected String getQueryPara(List<Object> paras, SqlData sqlData, Object model) {
// 定义可替换片段
String fromNext = "{FIELD_Front}";
String fromPrev = "{FIELD}";
String wherePrev = "{INNER}";
String[] lastCode = new String[]{"{WHERE}", "{GROUP}", "{HAVING}", "{ORDER}", "{LIMIT}"};
// 将SQL语句进行代码片段追加
String sql = sqlData.Sql;
for (String code : lastCode) {
if (sql.indexOf(code) == -1) {
sql += code;
}
}
// 处理字段以及代码片段
Map<String, Object> mapPara = new HashMap<String, Object>(); // 按照参数顺序缓存的参数
Map<String, List<String>> codeMap = new HashMap<String, List<String>>(); // 代码片段缓存
// 循环处理字段
for (SqlDataField field : sqlData.sqlDataFields) {
// 获取值
Object val = ObjectHelper.get(model, field.paraName);
// 不需要输入参数,仅仅只是代码片段
boolean isCode = StringHelper.isEmpty(field.paraName);
// 判断是否属于
if (!isCode) {
// 写入参数到对象中
mapPara.put(field.paraName, val);
// 判断是否属于条件
boolean isCondtion = field.codes.size() > 0 && field.auto;
// 处理参数
if (!isCondtion) {
// 进行SQL语句参数替换,后面增加一个空格,方便后续用正则表达式进行替换处理
sql = sql.replaceFirst("\\?", "@" + field.paraName + " ");
}
if (isCondtion && StringHelper.isEmpty(val)) {
continue;
}
}
// 判断代码片段是否合法
if (field.codes.size() % 2 == 1) {
throw new CodeException("代码片段" + this.getClass().getSimpleName() + ":" + sqlData.Name + ":" + field.paraName + "为单数");
}
// 处理代码片段
for (int i = 0; i < field.codes.size(); i = i + 2) {
String codeName = field.codes.get(i);
String codeValue = field.codes.get(i + 1);
codeValue = codeValue.replaceAll("\\?", "@" + field.paraName + " ");
addCodeMap(codeMap, codeName, codeValue);
}
}
// 正则表达式匹配代码片段,并根据代码片段获取数组进行增加
{
String regex = "\\{.*?\\}";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(sql);
// 寻找到的代码片段 不包含分括号
while (m.find()) {
String name = m.group();
// m.group(1);
List<String> codes = codeMap.containsKey(name) ? codeMap.get(name) : new ArrayList<String>();
String code = String.join("", codes);
sql = sql.replace(name, code);
}
}
// 通过正则表达式处理参数 @Name 并替换SQL语句成 ?
{
String regex = "@([a-zA-Z0-9_]+)";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(sql);
// 寻找到的代码片段 不包含分括号
while (m.find()) {
// SQL参数名称 @Name\s
String name = m.group();
// 对应的前台输入字段 Name
String field = m.group(1);
// 根据输入字段从参数中取值
Object val = mapPara.get(field);
// 判断是否为数组
if (val != null && (val instanceof List || val.getClass().isArray())) {
sql = getListSql(paras, sql, name, val);
} else {
// 当参数不为数组时,则直接增加
sql = sql.replaceFirst(name, "?");
val = this.getParaValue(val);
paras.add(val);
}
}
}
return sql;
}
/**
* 获取处理后的参数值
*
* @param val
* @return
*/
private Object getParaValue(Object val) {
if (val instanceof Boolean) {
val = 0;
}
val = StringHelper.toString(val);
return val;
}
/**
* 获取列表的SQL语句
*
* @param paras 参数
* @param sql SQL语句
* @param name 名称
* @param val 值
* @return 获取包含列表的SQL语句的值
*/
private String getListSql(List<Object> paras, String sql, String name, Object val) {
List list;
// 判断处理
boolean isList = val instanceof List;
if (isList) {
list = (List) val;
} else {
Object[] arr = (Object[]) val;
list = Arrays.asList(arr);
}
int length = list.size();
// 进行循环
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
Object item = list.get(i);
// 判断列表是否为常规对象
if (item == null || item instanceof Number || item.getClass().isEnum() || item instanceof String || item instanceof Date) {
addArrayIn(paras, sb, i, item);
} else if (item instanceof CaseSqlModel) {
addArrayCase(paras, sb, i, (CaseSqlModel) item);
} else {
addArrayTable(paras, sb, i, item);
}
}
// 生成最终的SQL语句
sql = sql.replaceFirst(name, sb.toString());
return sql;
}
/**
* 添加数组型参数
*
* @param paras 参数列表
* @param sb 字符串数组
* @param i 序号
* @param from 参数值
*/
private void addArrayIn(List<Object> paras, StringBuilder sb, int i, Object from) {
// 添加连接字符串
if (i > 0) {
sb.append(",");
}
// 添加参数SQL语句
sb.append("?");
Object to = this.getParaValue(from);
paras.add(to);
}
/**
* 添加 CASE型字段
*
* @param paras 参数列表
* @param sb 字符串数组
* @param i 序号
* @param from 参数值
*/
private void addArrayCase(List<Object> paras, StringBuilder sb, int i, CaseSqlModel from) {
// 添加连接字符串
if (i > 0) {
sb.append(",");
}
switch (from.getGroupType()) {
case CaseSqlModel.GroupTypeSUM:
sb.append("SUM");
break;
case CaseSqlModel.GroupTypeCOUNT:
sb.append("COUNT");
break;
case CaseSqlModel.GroupTypeMAX:
sb.append("MAX");
break;
case CaseSqlModel.GroupTypeMIN:
sb.append("MIN");
break;
case CaseSqlModel.GroupTypeAVG:
sb.append("AVG");
break;
default:
throw new CodeException("统计类型[" + from.getGroupType() + "]不支持");
}
sb.append("( CASE WHEN ");
sb.append(from.getCaseField());
sb.append(" ");
if (from.getCaseValue() != null) {
sb.append("=?");
paras.add(from.getCaseValue());
}
sb.append(from.getAndWhere());
sb.append(" THEN ");
if (!StringHelper.isEmpty(from.getValueField())) {
sb.append(from.getValueField());
} else if (!StringHelper.isEmpty(from.getValue())) {
sb.append("?");
paras.add(from.getValue());
}
sb.append(" ELSE 0 END ) AS ");
sb.append(from.getToName());
}
/**
* 添加表格型参数,将列表转换成表格
*
* @param paras 参数列表
* @param sb 字符串数组
* @param i 序号
* @param from 参数值
*/
private void addArrayTable(List<Object> paras, StringBuilder sb, int i, Object from) {
// 添加连接字符串
if (i > 0) {
sb.append(" UNION ALL ");
}
// 将对象转换为 Map 对象
Map to = new HashMap<String, Object>();
if (from instanceof Map) {
to = (Map) from;
} else {
ObjectHelper.writeWithFromClass(to, from);
}
// 生成SQL语句
int column = 0;
sb.append(" SELECT ");
// 处理列
for (Object oItemKey : to.keySet()) {
if (column > 0) {
sb.append(",");
}
String itemKey = StringHelper.toString(oItemKey);
sb.append("? AS " + itemKey);
// 处理参数
Object itemValue = to.get(oItemKey);
itemValue = this.getParaValue(itemValue);
paras.add(itemValue);
column++;
}
}
/**
* 将代码片段添加到SQL语句中
*
* @param codeMap
* @param name
* @param code
*/
private void addCodeMap(Map<String, List<String>> codeMap, String name, String code) {
if (!codeMap.containsKey(name)) {
codeMap.put(name, new ArrayList<String>());
}
List<String> arr = codeMap.get(name);
arr.add(code);
}
/**
* 根据缓存查询第一个单元格
*
* @param sql 需要执行的SQL语句
* @param paras SQL语句的参数
* @return 查询的结果
*/
protected Object queryCellWithCache(String sql, Object... paras) {
// 生成缓存的主键
String cacheKey = getCacheKey(Object.class, sql, paras);
// 获取缓存
Object cache = this.cacheList.get(cacheKey);
// 返回缓存
if (cache != null) {
return cache;
}
// 查询数据
Object ret = db.queryCell(sql, paras);
// 写入缓存
this.cacheList.put(cacheKey, ret);
return ret;
}
/**
* 执行查询SQL语句,并将数据缓存起来
*
* @param cls 返回的类型
* @param sql 需要执行的SQL语句
* @param paras 执行的SQL语句的参数
* @param <T> 返回的泛型
* @return 需要返回的数据
*/
protected <T> List<T> queryWithCache(Class<T> cls, String sql, Object... paras) {
// 生成缓存的主键
String cacheKey = getCacheKey(cls, sql, paras);
// 获取缓存
Object cache = this.cacheList.get(cacheKey);
// 返回缓存
if (cache != null) {
return (List<T>) cache;
}
// 查询数据
List<T> ret = db.query(cls, sql, paras);
// 写入缓存
this.cacheList.put(cacheKey, ret);
return ret;
}
/**
* 获取缓存的键值对
*
* @param cls 结果类型
* @param sql SQL语句
* @param paras SQL语句参数
* @return 返回的结果
*/
protected String getCacheKey(Class<?> cls, String sql, Object... paras) {
StringBuilder sb = new StringBuilder();
sb.append(cls.getName());
sb.append(":");
sb.append(sql);
for (Object para : paras) {
sb.append(":");
sb.append(para);
}
return StringHelper.md5(sb.toString());
}
}
package com.yanzuoguang.dao.Impl;
/**
* @Author : Light_PC
* @Description :
* @Date : 2017/12/7 17:36
* @ModiflyAuthor:
* @ModiflyDate: 2017/12/7 17:36
*/
public class CaseSqlModel {
public final static int GroupTypeSUM = 0;
public final static int GroupTypeCOUNT = 1;
public final static int GroupTypeAVG = 2;
public final static int GroupTypeMIN = 3;
public final static int GroupTypeMAX = 4;
public CaseSqlModel(String caseField, String caseValue, String valueField, String toName) {
this(GroupTypeSUM, caseField, caseValue, valueField, toName);
}
public CaseSqlModel(int groupType, String caseField, String caseValue, String valueField, String toName) {
this.GroupType = groupType;
this.CaseField = caseField;
this.CaseValue = caseValue;
this.ValueField = valueField;
this.ToName = toName;
this.AndWhere = "";
}
public CaseSqlModel(String caseField, String caseValue, Object value, String toName, String andWhere) {
this(GroupTypeSUM, caseField, caseValue, value, toName, andWhere);
}
public CaseSqlModel(int groupType, String caseField, String caseValue, Object value, String toName, String andWhere) {
this.GroupType = groupType;
this.CaseField = caseField;
this.CaseValue = caseValue;
this.Value = value;
this.ToName = toName;
this.AndWhere = andWhere;
}
public CaseSqlModel(String caseField, String caseValue, String valueField, String toName, String andWhere) {
this(GroupTypeSUM, caseField, caseValue, valueField, toName, andWhere);
}
public CaseSqlModel(int groupType, String caseField, String caseValue, String valueField, String toName, String andWhere) {
this.GroupType = groupType;
this.CaseField = caseField;
this.CaseValue = caseValue;
this.ValueField = valueField;
this.ToName = toName;
this.AndWhere = andWhere;
}
/**
* 统计纬度
*/
private int GroupType;
/**
* 需要判断的字段
*/
private String CaseField;
/**
* 需要判断的值
*/
private String CaseValue;
/**
* 需要统计的字段,和 Value 只能存在一个,ValueField优先级更高
*/
private String ValueField;
/**
* 需要统计的值,和 ValueField只能存在一个,ValueField优先级更高
*/
private Object Value;
/**
* 目标字段名称
*/
private String ToName;
/**
* 需要判断的CASE字段的附加条件
*/
private String AndWhere;
public int getGroupType() {
return GroupType;
}
public void setGroupType(int groupType) {
GroupType = groupType;
}
public String getCaseField() {
return CaseField;
}
public void setCaseField(String caseField) {
CaseField = caseField;
}
public String getCaseValue() {
return CaseValue;
}
public void setCaseValue(String caseValue) {
CaseValue = caseValue;
}
public String getValueField() {
return ValueField;
}
public void setValueField(String valueField) {
ValueField = valueField;
}
public Object getValue() {
return Value;
}
public void setValue(Object value) {
Value = value;
}
public String getToName() {
return ToName;
}
public void setToName(String toName) {
ToName = toName;
}
public String getAndWhere() {
return AndWhere;
}
public void setAndWhere(String andWhere) {
AndWhere = andWhere;
}
}
package com.yanzuoguang.dao.Impl;
import java.util.HashMap;
/**
* 行映射
* created by yanzu on 2017/5/31.
*/
public class MapRow extends HashMap<String,Object> {
}
package com.yanzuoguang.dao.Impl;
import java.util.ArrayList;
import java.util.List;
/**
* SQL语句基本信息
* created by yanzu on 2017/5/30.
*/
public class SqlData {
/**
* 对应的参数顺序
*/
public List<SqlDataField> sqlDataFields = new ArrayList<SqlDataField>();
/**
* SQL语句的名称
*/
public String Name;
/**
* SQL语句
*/
public String Sql;
/**
* 构造函数
*/
public SqlData() {
this("", "");
}
/**
* SQL语句的基本信息
*
* @param name SQL语句的名称
* @param sql 需要执行的SQL语句,其中可以包含大括号括起来的代码片段。 如: {WHERE}
* @param paras SQL语句参数名称数组
*/
public SqlData(String name, String sql, String... paras) {
this.Name = name;
this.Sql = sql;
for (String input : paras) {
this.add(input);
}
}
/**
* 根据字段名称获取字段
*
* @param fieldName
* @return
*/
public SqlDataField getField(String fieldName) {
String to = fieldName.toLowerCase().replaceAll("_", "");
for (SqlDataField sqlDataField : this.sqlDataFields) {
if (to.equals(sqlDataField.paraName.toLowerCase())) {
return sqlDataField;
}
}
return null;
}
/**
* 添加参数,当在SQL语句中存在参数时,用于处理。{@id} 代表前台输入参数字段为id
* 例子:
* SqlData sql = new SqlData("SQL_NAME","SELECT * FROM TABLE WHERE id=?");
* sql.add( "id" );
* 最终SQL语句为:
* SELECT * FROM TABLE WHERE id={id}"
*
* @param paraName 前台参数名称
*/
public SqlData add(String paraName) {
return addCodeExecute(paraName, "", false);
}
/**
* 添加常规代码片段,即不论如何都会将该代码片段增加到SQL语句中。
* 例子:
* SqlData sql = new SqlData("SQL_NAME","SELECT * FROM TABLE {INNER} WHERE 1=1 {WHERE}");
* sql.addCode(
* "{INNER}", " INNER JOIN TABLE_B " ,
* "{WHERE}", " AND 1=1" ,
* );
* 最终SQL语句为: (1=1 AND 会自动去掉)
* SELECT * FROM TABLE INNER JOIN TABLE_B WHERE 1=1"
*
* @param codes 代码片段
*/
public SqlData addCode(String... codes) {
return addCodeExecute("", "", false, codes);
}
/**
* 当前台参数传入值时,在 {WHERE} 条件中增加条件,并增加附加的代码片段
* <p>
* 例子:
* SqlData sql = new SqlData("SQL_NAME","SELECT * FROM TABLE {INNER} WHERE 1=1 {WHERE}");
* sql.add("id" , " AND id = ? ",
* "{INNER}", " INNER JOIN TABLE_B "
* );
* 最终SQL语句为: (1=1 AND 会自动去掉)
* SELECT * FROM TABLE INNER JOIN TABLE_B WHERE id = {@id}
*
* @param paraName 前台参数名称
* @param cond {WHERE}代码片段中的条件
* @param codes 扩展代码片段
*/
public SqlData add(String paraName, String cond, String... codes) {
return addCodeExecute(paraName, cond, true, codes);
}
/**
* 当前台参数传入值时,增加附加的代码片段
* <p>
* 例子:
* SqlData sql = new SqlData("SQL_NAME","SELECT * FROM TABLE {INNER} WHERE 1=1 {WHERE}");
* sql.addPara("id" ,
* "{WHERE}", " AND id = ? ",
* "{INNER}", " INNER JOIN TABLE_B "
* );
* 最终SQL语句为: (1=1 AND 会自动去掉)
* SELECT * FROM TABLE INNER JOIN TABLE_B WHERE id = {@id}
*
* @param paraName 字段
* @param codes 代码片段
*/
public SqlData addPara(String paraName, String... codes) {
return addCodeExecute(paraName, "", true, codes);
}
/**
* 不论前台参数是否有值,在 {WHERE} 条件中增加条件,并增加附加的代码片段
* <p>
* 例子:
* SqlData sql = new SqlData("SQL_NAME","SELECT * FROM TABLE {INNER} WHERE 1=1 {WHERE}");
* sql.add("id" , " AND id = ? ",
* "{INNER}", " INNER JOIN TABLE_B "
* );
* 最终SQL语句为: (1=1 AND 会自动去掉)
* SELECT * FROM TABLE INNER JOIN TABLE_B WHERE id = {@id}
*
* @param paraName 前台参数名称
* @param cond {WHERE}代码片段中的条件
* @param codes 扩展代码片段
*/
public SqlData addConst(String paraName, String cond, String... codes) {
return addCodeExecute(paraName, cond, false, codes);
}
/**
* 不论前台参数是否有值,增加代码片段
* <p>
* 例子:
* SqlData sql = new SqlData("SQL_NAME","SELECT * FROM TABLE {INNER} WHERE 1=1 {WHERE}");
* sql.addPara("id" ,
* "{WHERE}", " AND id = ? ",
* "{INNER}", " INNER JOIN TABLE_B "
* );
* 最终SQL语句为: (1=1 AND 会自动去掉)
* SELECT * FROM TABLE INNER JOIN TABLE_B WHERE id = {@id}
*
* @param paraName 前台参数名称
* @param codes 代码片段
*/
public SqlData addParaConst(String paraName, String... codes) {
return addCodeExecute(paraName, "", false, codes);
}
/**
* 添加SQL语句的执行方法
*
* @param paraName 参数名称
* @param cond 包含条件
* @param auto 未false时表示属于必须输入的参数
* @param codes 代码片段
* @return
*/
private SqlData addCodeExecute(String paraName, String cond, boolean auto, String... codes) {
SqlDataField sql = new SqlDataField(paraName, cond);
for (String code : codes) {
sql.codes.add(code);
}
sql.auto = auto;
this.sqlDataFields.add(sql);
return this;
}
/**
* 删除字段
*
* @param fieldName 字段名称
* @return
*/
public SqlData removeField(String fieldName) {
SqlDataField field = this.getField(fieldName);
if (field != null) {
this.sqlDataFields.remove(field);
}
return this;
}
/**
* 删除删除标记字段
*
* @return
*/
public SqlData removeFieldRemove() {
this.removeField(TableStruct.ISREMOVE_CONTANS);
return this;
}
/**
* 将当前SQL语句进行复制
*
* @return 复制的结果
*/
public SqlData copy() {
SqlData to = new SqlData(this.Name, this.Sql);
for (SqlDataField sqlDataField : this.sqlDataFields) {
to.sqlDataFields.add(sqlDataField.copy());
}
return to;
}
/**
* 设置SQL语句名称
*
* @param name SQL语句名称
* @return
*/
public SqlData setName(String name) {
this.Name = name;
return this;
}
}
package com.yanzuoguang.dao.Impl;
import java.util.ArrayList;
import java.util.List;
/**
* SQL语句的字段
*/
public class SqlDataField {
/**
* 前台参数名称,当没有前台参数时,则把当前字段当常量代码片段处理
*/
public String paraName = "";
/**
* 是否根据前台参数自动添加,false时保持永久添加模式
*/
public boolean auto = true;
/**
* 代码片段
*/
public List<String> codes = new ArrayList<String>();
/**
* 构造函数
*
* @param paraName 前台输入字段
*/
public SqlDataField(String paraName) {
this(paraName, "");
}
/**
* 构造函数
*
* @param paraName 前台输入字段
* @param cond 条件
*/
public SqlDataField(String paraName, String cond) {
this.paraName = paraName;
this.add(cond);
}
/**
* 复制实体
*
* @return
*/
public SqlDataField copy() {
SqlDataField to = new SqlDataField(this.paraName);
to.auto = this.auto;
to.codes.addAll(this.codes);
return to;
}
/**
* 添加条件
*
* @param cond
* @return
*/
public SqlDataField add(String cond) {
return this.add("{WHERE}", cond);
}
/**
* 添加条件
*
* @param codeName 字段名称
* @param codeValue 代码内容
* @return
*/
public SqlDataField add(String codeName, String codeValue) {
if ("".equals(codeValue) || codeValue == null) {
return this;
}
this.codes.add(codeName);
this.codes.add(codeValue);
return this;
}
/**
* 清除所有的代码片段
*
* @return
*/
public SqlDataField clear() {
this.codes.clear();
return this;
}
}
package com.yanzuoguang.dao.Impl;
import java.util.ArrayList;
import java.util.List;
/**
* Created by yanzu on 2017/6/6.
*/
public class TableFieldString {
/**
* 其他字段
*/
public List<String> Fields = new ArrayList<String>();
/**
* 构造函数
*
* @param fields
*/
public TableFieldString(String... fields) {
for (String field : fields) {
this.Fields.add(field);
}
}
/**
* 构造函数
*
* @param fields
*/
public TableFieldString(List<String> fields) {
for (String field : fields) {
this.Fields.add(field);
}
}
}
package com.yanzuoguang.dao.Impl;
/**
* 表结构的基本信息
* created by yanzu on 2017/5/30.
*/
public class TableFieldVo {
public TableFieldVo() {
this("id");
}
public TableFieldVo(String name) {
this(name, name);
}
public TableFieldVo(String name, String inputName) {
this(name, inputName, String.class);
}
public TableFieldVo(String name, String inputName, Class<?> type) {
this.name = name;
this.lName = name.toLowerCase();
this.inputName = inputName;
this.inputLName = inputName.toLowerCase();
this.type = type;
}
public String name;
public String lName;
public String inputName;
public String inputLName;
public Class<?> type = String.class;
;
}
package com.yanzuoguang.dao.Impl;
import com.yanzuoguang.util.cache.MemoryCache;
import com.yanzuoguang.util.exception.CodeException;
import com.yanzuoguang.util.helper.StringHelper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 缓存的SQL语句信息
* created by yanzu on 2017/5/30.
*/
public class TableSqlCache {
/**
* 分页标记
*/
public static final String PAGE_SIZE_TAG = "_PageSize";
/**
* 表信息
*/
public TableStruct Table;
/**
* 缓存的SQL信息
*/
public MemoryCache<SqlData> Sqls = new MemoryCache<SqlData>();
/**
* 构造函数
*/
public TableSqlCache() {
this.Table = new TableStruct();
}
/**
* 添加SQL语句组
*
* @param sqls
*/
public void add(SqlData... sqls) {
for (SqlData sql : sqls) {
this.add(sql);
}
}
/**
* 添加可执行的SQL语句
*
* @param sql SQL语句
*/
public SqlData add(SqlData sql) {
if (sql != null) {
this.Sqls.put(sql.Name, sql);
}
return sql;
}
/**
* 添加SQL
*
* @param sqlName SQL名称
* @param sql SQL语句
* @param fields 字段
*/
public SqlData add(String sqlName, String sql, String... fields) {
SqlData model = new SqlData(sqlName, sql, fields);
return this.add(model);
}
/**
* 根据现有SQL语句生成分页查询
*
* @param from
* @param sql
* @return
*/
public SqlData addPageSize(SqlData from, String sql) {
SqlData to = from.copy();
to.Sql = sql;
to.Name += TableSqlCache.PAGE_SIZE_TAG;
return this.add(to);
}
/**
* 生成GroupSQL语句
*
* @param tableWhereField
* @param addField
*/
public void addGroup(TableFieldString tableWhereField, TableFieldString addField) {
this.Table.addGroupSql(this, tableWhereField, addField);
}
/**
* 生成GroupSQL语句
*
* @param sqlName
* @param whereFields
*/
public void addSaveWith(String sqlName, TableFieldString whereFields) {
this.Table.addSaveWithSql(this, sqlName, whereFields);
}
/**
* 生成Group执行的SQL语句
*
* @param sqlName
* @param tableWhereField
* @param addField
* @param sql
* @param
*/
public List<SqlData> addGroupList(String sqlName, TableFieldString tableWhereField, TableFieldString addField,
String sql, String... field) {
Map<String, Boolean> sqlFieldHas = new HashMap<String, Boolean>();
Map<String, Boolean> sqlFieldWhere = new HashMap<String, Boolean>();
Map<String, Boolean> sqlFieldAdd = new HashMap<String, Boolean>();
SqlData sqlInit = new SqlData(sqlName + "_GroupInit", "", field);
SqlData sqlAdd = new SqlData(sqlName + "_GroupAdd", "", field);
// 1. 获取SQL语句中已包含的字段
String sqlField = sql.substring(0, sql.replace("\n", " ")
.replace("\t", " ")
.toLowerCase().indexOf(" from ")) + ",";
// 去掉字段中的函数
sqlField = sqlField.replaceAll("\\(.+?\\)", "");
String regex = "[\\s,]*(\\S+?)\\s*?,";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(sqlField);
// 寻找到的代码片段 不包含分括号
while (m.find()) {
String name = m.group(1);
if (name.indexOf(".") >= -1) {
name = name.substring(name.indexOf(".") + 1);
}
sqlFieldHas.put(name.toLowerCase(), true);
}
// 2. 判断所有纬度字段是否已经存在
for (String item : tableWhereField.Fields) {
String name = item.toLowerCase();
if (!sqlFieldHas.containsKey(name)) {
throw new CodeException("SQL语句" + item + "不存在纬度" + item);
}
sqlFieldWhere.put(name, true);
}
for (String item : addField.Fields) {
String name = item.toLowerCase();
sqlFieldAdd.put(name, true);
}
// 3. 生成SQL语句
String selectModel = "SELECT {FromField} FROM ( {SQL} )t";
String initModel = "INSERT INTO {Table}( {CreateField} ) " +
"SELECT {FromInitField} FROM( {SelectSQL} )a " +
"LEFT JOIN {Table} AS b ON a.{Key} = b.{Key} WHERE b.{Key} IS NULL";
String addModel = "UPDATE {Table} AS a INNER JOIN ( {SelectSQL} ) AS b ON a.{Key} = b.{Key} SET {addConst} ";
// 定义需要处理的SQL对象
Map<String, StringBuilder> map = new HashMap<String, StringBuilder>();
addString(map, "{SQL}", sql);
addString(map, "{Table}", this.Table.getName());
if (this.Table.getKeyType() == String.class) {
addString(map, "{Key}", this.Table.getKeyName());
} else if (!StringHelper.isEmpty(this.Table.getMD5KeyName())) {
addString(map, "{Key}", this.Table.getMD5KeyName());
} else {
throw new CodeException("表中未包含MD5字段");
}
String lowerKey = this.Table.getKeyName().toLowerCase();
String lowerMD5Key = this.Table.getMD5KeyName().toLowerCase();
List<TableFieldVo> allField = new ArrayList<TableFieldVo>();
allField.add(this.Table.getKey());
allField.addAll(this.Table.getFields());
for (TableFieldVo fieldVo : allField) {
String fieldName = fieldVo.name;
String fieldLName = fieldVo.lName;
if (fieldLName.equals(lowerKey) && this.Table.getKeyType() != String.class) {
continue;
}
// 处理逗号
addFlag(map, "{CreateField}", ",");
addFlag(map, "{FromInitField}", ",");
addString(map, "{CreateField}", fieldName);
if (fieldLName.equals(lowerKey) || fieldLName.equals(lowerMD5Key)) {
addFlag(map, "{FromField}", ",");
// 处理需要MD5的字段
addString(map, "{FromField}", "MD5(CONCAT(");
int i = 0;
for (String whereField : tableWhereField.Fields) {
if (i > 0) {
addString(map, "{FromField}", ",':',");
}
addString(map, "{FromField}", whereField);
i++;
}
addString(map, "{FromField}", ")) AS ");
addString(map, "{FromField}", fieldName);
addString(map, "{FromInitField}", "a." + fieldName);
} else {
// 处理常规字段
if (sqlFieldAdd.containsKey(fieldLName) && sqlFieldHas.containsKey(fieldLName)) {
addFlag(map, "{addConst}", ",");
addString(map, "{addConst}", "a." + fieldName + "=a." + fieldName + "+b." + fieldName);
}
if (sqlFieldHas.containsKey(fieldLName)) {
addFlag(map, "{FromField}", ",");
addString(map, "{FromField}", fieldName);
}
if (sqlFieldWhere.containsKey(fieldLName)) {
addString(map, "{FromInitField}", "a." + fieldName);
} else if (sqlFieldAdd.containsKey(fieldLName)) {
addString(map, "{FromInitField}", "0 AS " + fieldName);
} else {
addString(map, "{FromInitField}", "a." + fieldName);
System.err.println("纬度" + this.Table.getName() + "->" + sqlName + "->" + fieldName + "存在,但是没有统计");
}
}
}
// 最终SQL语句处理
selectModel = replaceString(map, selectModel);
addString(map, "{SelectSQL}", selectModel);
sqlInit.Sql = replaceString(map, initModel);
sqlAdd.Sql = replaceString(map, addModel);
this.add(sqlInit);
this.add(sqlAdd);
List<SqlData> ret = new ArrayList<SqlData>();
ret.add(sqlInit);
ret.add(sqlAdd);
return ret;
}
/**
* 生成该字段值是否存在的SQL语句
*
* @param sqlName SQL语句名称
* @param fields 字段
*/
public void addExist(String sqlName, String... fields) {
this.Table.addExist(this, sqlName, fields);
}
private void addString(Map<String, StringBuilder> map, String name, String value) {
if (!map.containsKey(name)) {
map.put(name, new StringBuilder());
}
map.get(name).append(value);
}
private void addFlag(Map<String, StringBuilder> map, String name, String flag) {
if (!map.containsKey(name)) {
addString(map, name, "");
} else if (map.get(name).length() > 0) {
addString(map, name, flag);
}
}
private String replaceString(Map<String, StringBuilder> map, String sql) {
for (String key : map.keySet()) {
sql = sql.replace(key, map.get(key).toString());
}
return sql;
}
}
package com.yanzuoguang.dao.Impl;
import com.yanzuoguang.dao.DaoConst;
import com.yanzuoguang.dao.TableAnnotation;
import com.yanzuoguang.util.helper.StringHelper;
import com.yanzuoguang.util.obj.MethodField;
import com.yanzuoguang.util.obj.ObjectHelper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 表结构的基本信息
* created by yanzu on 2017/5/30.
*/
public class TableStruct {
// 声明SQL语句模型
private static final String insertModel = "INSERT INTO {TABLE}({FIELD}) VALUES({VALUES})";
private static final String updateModel = "UPDATE {TABLE} SET {FIELD} WHERE 1=1 {WHERE}";
private static final String removeModel = "DELETE FROM {TABLE} WHERE 1=1 {WHERE}";
private static final String loadModel = "SELECT a.*{FIELD} FROM {TABLE} AS a {INNER} WHERE 1=1 {WHERE}";
private static final String VERSON = "verson";
private static final String ISREMOVE = "isremove";
public static final String ISREMOVE_CONTANS = "contans____isremove";
/**
* 表名称
*/
private String Name;
/**
* 主键名称
*/
private TableFieldVo Key;
/**
* MD5KEY
*/
private TableFieldVo MD5Key;
/**
* 其他字段
*/
private List<TableFieldVo> Fields = new ArrayList<TableFieldVo>();
public List<TableFieldVo> getFields() {
return Fields;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public TableFieldVo getKey() {
return Key;
}
public TableFieldVo getMD5Key() {
return MD5Key;
}
public String getKeyName() {
return this.Key.inputName;
}
public String getMD5KeyName() {
return MD5Key != null ? MD5Key.inputName : null;
}
public Class<?> getKeyType() {
return this.Key.type;
}
/**
* 构造函数
*/
public TableStruct() {
this.Name = "";
this.Key = new TableFieldVo("id");
}
/**
* 通过实体的字段来创建表结构信息
*
* @param name 表名称
* @param cls 关联的实体,主键放在第一位,其他字段放到后面;需要注意的是必需和表结构对应起来,会有隐性BUG,比如说在实体中增加了字段,会导致增加修改失败
*/
public TableStruct(String name, Class<?> cls) {
this.Name = name;
// 获取实体中的所有字段信息,包含get、set、field
HashMap<String, MethodField> fields = ObjectHelper.getTypeField(cls);
// 遍历字段
for (Map.Entry<String, MethodField> entry : fields.entrySet()) {
// 字段信息获取
MethodField field = entry.getValue();
if (field.field == null && field.getMethod == null) {
continue;
}
String fieldName = field.name;
String fieldInputName = field.name;
Class<?> fieldType = String.class;
TableAnnotation annotation = null;
if (field.field != null) {
annotation = field.field.getAnnotation(TableAnnotation.class);
fieldType = field.field.getType();
} else if (field.getMethod != null) {
annotation = field.getMethod.getAnnotation(TableAnnotation.class);
fieldType = field.getMethod.getReturnType();
}
if (annotation != null) {
fieldName = annotation.value();
}
TableFieldVo vo = new TableFieldVo(fieldName, fieldInputName, fieldType);
// 判断是否属于统计字段
if (vo.inputLName.equals("md5key")) {
this.MD5Key = vo;
}
// 判断是否是主键,获取主键数据类型
if (this.Key == null) {
this.Key = vo;
} else {
this.Fields.add(vo);
}
}
}
public TableFieldVo getField(String name) {
if (StringHelper.isEmpty(name)) {
return null;
}
for (TableFieldVo fieldVo : this.Fields) {
if (fieldVo.lName.equals(name.toLowerCase()) || fieldVo.inputLName.equals(name.toLowerCase())) {
return fieldVo;
}
}
return null;
}
/**
* 判断是否包含版本号字段
*
* @return
*/
public TableFieldVo getVersion() {
return this.getField(VERSON);
}
/**
* 判断是否包含remove字段
*
* @return
*/
private TableFieldVo getRemove() {
return this.getField(ISREMOVE);
}
/**
* 通过表结构自动生成SQL语句
*
* @return
*/
public void init(TableSqlCache table) {
table.Table = this;
if (!StringHelper.isEmpty(this.Name)) {
table.add(releaseSqlCreate(), releaseSqlUpdate(), ReeleaseSqlRemove(), releaseSqlLoad());
}
}
/**
* 生成创建的SQL语句
*
* @return
*/
private SqlData releaseSqlCreate() {
// 生成添加的SQL语句
String text = insertModel.replace("{TABLE}", this.Name);
SqlData sql = new SqlData(DaoConst.Create, text);
String flag = "";
if (this.getKeyType() == String.class) {
sql.addParaConst(this.Key.inputName, "{FIELD}", this.Key.name, "{VALUES}", "?");
flag = ",";
}
for (TableFieldVo field : this.Fields) {
sql.addParaConst(field.inputName, "{FIELD}", flag + field.name, "{VALUES}", flag + "?");
flag = ",";
}
return sql;
}
/**
* 生成修改的SQL语句
*
* @return
*/
private SqlData releaseSqlUpdate() {
// 生成添加的SQL语句
String text = updateModel.replace("{TABLE}", this.Name);
SqlData sql = new SqlData(DaoConst.Update, text);
TableFieldVo removeField = this.getRemove();
TableFieldVo versionField = this.getVersion();
sql.addParaConst(this.Key.inputName,
"{FIELD}", "" + this.Key.name + "=" + this.Key.name,
"{WHERE}", " AND " + this.Key.name + "=?");
for (TableFieldVo field : this.Fields) {
if (field == removeField || field == versionField) {
continue;
}
sql.addParaConst(field.inputName, "{FIELD}", "," + field.name + "=?");
}
if (removeField != null) {
sql.addParaConst(removeField.inputName, "{WHERE}", " AND " + removeField.name + "=0");
}
if (versionField != null) {
sql.addParaConst(versionField.inputName,
"{FIELD}", "," + versionField.name + "=1+" + versionField.name,
"{WHERE}", " AND " + versionField.name + "=?");
}
return sql;
}
/**
* 生成删除的SQL语句
*
* @return
*/
private SqlData ReeleaseSqlRemove() {
TableFieldVo removeField = this.getRemove();
TableFieldVo versionField = this.getVersion();
if (removeField != null) {
// 生成添加的SQL语句
String text = updateModel.replace("{TABLE}", this.Name);
SqlData sql = new SqlData(DaoConst.Remove, text);
sql.addCode("{FIELD}", removeField.name + "=1");
if (versionField != null) {
sql.addCode("{FIELD}", "," + versionField.name + "=1+" + versionField.name);
}
addWhereField(sql, "");
return sql;
} else {
String text = removeModel.replace("{TABLE}", this.Name);
SqlData sql = new SqlData(DaoConst.Remove, text);
addWhereField(sql, "");
return sql;
}
}
/**
* 生成加载的SQL语句
*
* @return
*/
private SqlData releaseSqlLoad() {
// 生成添加的SQL语句
String text = loadModel.replace("{TABLE}", this.Name);
SqlData sql = new SqlData(DaoConst.Load, text);
addWhereField(sql, "a.");
return sql;
}
/**
* 当前当前表所有字段的等于SQL语句
*
* @param sql
*/
private void addWhereField(SqlData sql, String tag) {
TableFieldVo removeField = this.getRemove();
sql.add(this.Key.inputName, " AND " + tag + this.Key.name + "=?");
for (TableFieldVo field : this.Fields) {
sql.add(field.inputName, " AND " + tag + field.name + "=?");
}
if (removeField != null) {
sql.addConst(ISREMOVE_CONTANS, " AND " + tag + removeField.name + "=0");
}
}
/**
* 生成统计的SQL语句
*
* @param sqlTableData 需要生成的实体
* @param whereFields WHERE字段
* @param updateFields 需要增加的值的字段
*/
public void addGroupSql(TableSqlCache sqlTableData, TableFieldString whereFields, TableFieldString updateFields) {
sqlTableData.add(this.releaseSqlWhere(DaoConst.GroupQuery, loadModel, whereFields));
sqlTableData.add(this.releaseSql(DaoConst.GroupAdd, updateModel, "{FIELD}={FIELD}+?", updateFields, new TableFieldString(this.Key.name)));
}
/**
* 生成SQL语句
*
* @param name
* @param model
* @param whereFields
* @return
*/
public SqlData releaseSqlWhere(String name, String model, TableFieldString whereFields) {
return this.releaseSql(name, model, "", new TableFieldString(), whereFields);
}
/**
* 生成SQL语句
*
* @param name SQL语句名称
* @param model SQL语句模板
* @param valueModel 值字段模板
* @param valueFields 值字段
* @param whereFields WHERE字段
* @return
*/
public SqlData releaseSql(String name, String model, String valueModel, TableFieldString valueFields, TableFieldString whereFields) {
// 参数字段
List<String> paraFields = new ArrayList<String>();
// 生成添加的SQL语句
StringBuilder sbField = new StringBuilder();
for (String field : valueFields.Fields) {
if (sbField.length() > 0) {
sbField.append(",");
}
sbField.append(valueModel.replace("{FIELD}", field));
paraFields.add(field);
}
StringBuilder sbWhere = new StringBuilder();
for (String field : whereFields.Fields) {
sbWhere.append(" AND ");
sbWhere.append(field);
sbWhere.append("=?");
paraFields.add(field);
}
String[] fields = new String[paraFields.size()];
fields = paraFields.toArray(fields);
// 生成修改的SQL语句
String sql = model.replace("{TABLE}", this.Name).replace("{FIELD}", sbField.toString()).replace("{WHERE}", sbWhere.toString());
SqlData ret = new SqlData(name, sql, fields);
return ret;
}
/**
* 生成根据某些字段不存在则保存的SQL语句
*
* @param tableStruct
* @param sqlName
* @param whereFields
*/
public void addSaveWithSql(TableSqlCache tableStruct, String sqlName, TableFieldString whereFields) {
tableStruct.add(this.releaseSqlWhere(sqlName, loadModel, whereFields));
}
/**
* 生成判断数据是否存在的SQL语句
*
* @param sqlTableData
* @param sqlName
* @param fields
*/
public void addExist(TableSqlCache sqlTableData, String sqlName, String[] fields) {
String text = loadModel.replace("{TABLE}", this.Name);
SqlData sql = new SqlData(sqlName, text);
sql.addPara(this.Key.name, "{WHERE}", " AND a." + this.Key + "<>?");
for (String field : fields) {
sql.addParaConst(field, "{WHERE}", " AND a." + field + "=?");
}
if (getRemove() != null) {
sql.addParaConst(ISREMOVE_CONTANS, "{WHERE}", " AND " + "a." + ISREMOVE + "=0");
}
sqlTableData.add(sql);
}
}
package com.yanzuoguang.dao;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 途比达列明映射
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface TableAnnotation {
/**
* 名称
*
* @return
*/
String value();
}
package com.yanzuoguang.db.db;
package com.yanzuoguang.db;
import com.yanzuoguang.util.vo.MapRow;
......
package com.yanzuoguang.db.db.Impl;
package com.yanzuoguang.db.Impl;
import com.yanzuoguang.db.db.extend.ConfigDb;
import com.yanzuoguang.extend.ConfigDb;
import com.yanzuoguang.util.log.Log;
import com.yanzuoguang.util.obj.ObjectHelper;
import com.yanzuoguang.util.vo.MapRow;
......
package com.yanzuoguang.db.db.Impl;
package com.yanzuoguang.db.Impl;
import com.yanzuoguang.db.db.DbExecute;
import com.yanzuoguang.db.DbExecute;
import com.yanzuoguang.util.vo.MapRow;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
......@@ -17,11 +17,11 @@ import java.util.List;
@Component
public class DbExecuteImpl implements DbExecute {
@Autowired
@Resource
@Qualifier("jdbcTemplate")
private JdbcTemplate jdbc;
@Autowired
@Resource
private DbPrintSql printSql;
/**
......
package com.yanzuoguang.db.db.Impl;
package com.yanzuoguang.db.Impl;
import com.yanzuoguang.db.db.extend.ConfigDb;
import com.yanzuoguang.extend.ConfigDb;
import com.yanzuoguang.util.helper.StringHelper;
import com.yanzuoguang.util.log.Log;
import org.springframework.stereotype.Component;
......
package com.yanzuoguang.extend;
/**
* 打印SQL日志
*/
public class ConfigDb {
/**
* 打印映射日志
*/
public static final boolean PrintMapper = false;
/**
* 打印SQL日志
*/
public static boolean PrintSql = false;
/**
* 判断是否匹配过滤
*/
public static String PrintSqlFilter = "";
}
package com.yanzuoguang.service;
import java.util.List;
/**
* 基本服务接口
* created by yanzu on 2017/5/29.
*/
public interface BaseService<T> {
/**
* 创建数据
*
* @param models 需要创建的数据
*/
List<String> create(T... models);
/**
* 修改数据
*
* @param models 需要修改的数据
*/
List<String> update(T... models);
/**
* 保存数据
*
* @param models 需要保存的数据
*/
List<String> save(T... models);
/**
* 删除数据
*
* @param models 需要删除的数据
*/
List<String> remove(T... models);
/**
* 加载数据
*
* @param models 需要删除的数据
*/
List<T> load(T... models);
}
package com.yanzuoguang.service.Impl;
import com.yanzuoguang.dao.BaseDao;
import com.yanzuoguang.service.BaseService;
import com.yanzuoguang.util.exception.CodeException;
import com.yanzuoguang.util.helper.StringHelper;
import java.util.ArrayList;
import java.util.List;
/**
* 基本服务实现
* created by yanzu on 2017/5/31.
*/
public abstract class BaseServiceImpl<T> implements BaseService<T> {
/**
* 数据类的类型
*/
protected Class<T> dataClass;
/**
* 标识
*/
protected String tag;
/**
* 构造函数
*
* @param cls
*/
public BaseServiceImpl(Class<T> cls, String tag) {
this.dataClass = cls;
this.tag = tag;
}
/**
* @param
* @return
* @description 获取Dao类来处理
*/
protected abstract BaseDao getDao();
/**
* 创建数据
*
* @param models 需要创建的数据
*/
public List<String> create(T... models) {
List<String> ids = new ArrayList<String>();
for (T t : models) {
String id = createItem(t);
ids.add(id);
}
return ids;
}
/**
* 创建一项
*
* @param item
* @return
*/
protected String createItem(T item) {
String id = this.getDao().create(item);
check("创建", this.tag, id);
return id;
}
/**
* 修改数据
*
* @param models 需要修改的数据
*/
public List<String> update(T... models) {
List<String> ids = new ArrayList<String>();
for (T t : models) {
String id = updateItem(t);
ids.add(id);
}
return ids;
}
/**
* 修改一项数据
*
* @param item
* @return
*/
protected String updateItem(T item) {
String id = this.getDao().update(item);
check("修改", this.tag, id);
return id;
}
/**
* 保存数据
*
* @param models 需要保存的数据
*/
public List<String> save(T... models) {
List<String> ids = new ArrayList<String>();
for (T item : models) {
String id = saveItem(item);
ids.add(id);
}
return ids;
}
/**
* 保存其中一项
*
* @param item
* @return
*/
protected String saveItem(T item) {
String id = this.getDao().save(item);
check("保存", this.tag, id);
return id;
}
/**
* 删除数据
*
* @param models 需要删除的数据
*/
public List<String> remove(T... models) {
List<String> ids = new ArrayList<String>();
for (T item : models) {
String id = removeItem(item);
ids.add(id);
}
return ids;
}
/**
* 删除其中一项
*
* @param item
* @return
*/
protected String removeItem(T item) {
String id = this.getDao().remove(item);
check("删除", this.tag, id);
return id;
}
/**
* 加载数据
*
* @param models 需要删除的数据
*/
public List<T> load(T... models) {
List<T> tos = new ArrayList<T>();
for (T item : models) {
T to = loadItem(item);
tos.add(to);
}
return tos;
}
/**
* 加载单个数据
*
* @param item
* @return
*/
protected T loadItem(T item) {
T to = this.getDao().load(item, dataClass);
check("加载", this.tag, to);
return to;
}
/**
* 检测编号
*
* @param opTag 操作标识
* @param serviceTag 服务标识
* @param id ID编号
*/
private void check(String opTag, String serviceTag, Object id) {
if (StringHelper.isEmpty(id)) {
throw new CodeException(opTag + serviceTag + "失败,该数据可能已被修改");
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment