SqlMapper逻辑优化,sql解析逻辑分离到SqlParser。
This commit is contained in:
+9
-93
@@ -25,16 +25,10 @@ import fun.asgc.neutrino.core.annotation.Component;
|
||||
import fun.asgc.neutrino.core.annotation.NonIntercept;
|
||||
import fun.asgc.neutrino.core.aop.Invocation;
|
||||
import fun.asgc.neutrino.core.aop.interceptor.Interceptor;
|
||||
import fun.asgc.neutrino.core.cache.Cache;
|
||||
import fun.asgc.neutrino.core.cache.MemoryCache;
|
||||
import fun.asgc.neutrino.core.db.annotation.*;
|
||||
import fun.asgc.neutrino.core.db.template.JdbcTemplate;
|
||||
import fun.asgc.neutrino.core.util.*;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -45,28 +39,26 @@ import java.util.Map;
|
||||
@NonIntercept
|
||||
@Component
|
||||
public class SqlMapperInterceptor implements Interceptor {
|
||||
|
||||
private static final Cache<Method, Params> paramsCache = new MemoryCache<>();
|
||||
|
||||
@Override
|
||||
public void intercept(Invocation inv) throws Exception {
|
||||
JdbcTemplate jdbcTemplate = BeanManager.getBean(JdbcTemplate.class);
|
||||
Assert.notNull(jdbcTemplate, "JdbcTemplate未注入,调用失败!");
|
||||
Params params = getParams(inv.getTargetMethod());
|
||||
if (null == params) {
|
||||
SqlParser sqlParser = SqlParser.getInstance(inv.getTargetMethod());
|
||||
if (null == sqlParser) {
|
||||
return;
|
||||
}
|
||||
|
||||
String sql = params.getSql();
|
||||
Class<?> resultType = params.getResultType();
|
||||
String sql = sqlParser.getSql();
|
||||
Class<?> resultType = sqlParser.getResultType();
|
||||
Class<?> resultComponentType = sqlParser.getResultComponentType();
|
||||
Object res = null;
|
||||
if (params.isSelect()) {
|
||||
if (params.isReturnCollection()) {
|
||||
res = jdbcTemplate.queryForList(resultType, sql, inv.getArgs());
|
||||
if (sqlParser.isSelect()) {
|
||||
if (sqlParser.isReturnCollection()) {
|
||||
res = jdbcTemplate.queryForList(resultComponentType, sql, inv.getArgs());
|
||||
} else {
|
||||
res = jdbcTemplate.query(resultType, sql, inv.getArgs());
|
||||
}
|
||||
} else if (params.isInsert() || params.isDelete() || params.isUpdate()) {
|
||||
} else if (sqlParser.isInsert() || sqlParser.isDelete() || sqlParser.isUpdate()) {
|
||||
int argsCount = ArrayUtil.isEmpty(inv.getArgs()) ? 0 : inv.getArgs().length;
|
||||
if (argsCount == 1 && inv.getArgs()[0] instanceof Map) {
|
||||
res = jdbcTemplate.updateByMap(sql, (Map)inv.getArgs()[0]);
|
||||
@@ -78,80 +70,4 @@ public class SqlMapperInterceptor implements Interceptor {
|
||||
}
|
||||
inv.setReturnValue(TypeUtil.conversion(res, resultType));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取参数
|
||||
* @param method
|
||||
* @return
|
||||
*/
|
||||
private static Params getParams(Method method) throws Exception {
|
||||
return LockUtil.doubleCheckProcess(
|
||||
() -> !paramsCache.containsKey(method),
|
||||
method,
|
||||
() -> {
|
||||
String sign = String.format("%s#%s", method.getDeclaringClass().getName(), method.getName());
|
||||
Params params = null;
|
||||
ResultType resultType = method.getAnnotation(ResultType.class);
|
||||
Class<?> resultClass = (null == resultType) ? null : resultType.value();
|
||||
|
||||
if (method.isAnnotationPresent(Select.class)) {
|
||||
// 查询
|
||||
Select select = method.getAnnotation(Select.class);
|
||||
String sql = select.value();
|
||||
if (StringUtil.isEmpty(sql)) {
|
||||
throw new RuntimeException(String.format("%s sql不能为空!", sign));
|
||||
}
|
||||
boolean isReturnCollection = Collection.class.isAssignableFrom(method.getReturnType());
|
||||
if (isReturnCollection && null == resultClass) {
|
||||
throw new RuntimeException(String.format("%s 请指名实体类型!", sign));
|
||||
}
|
||||
params = new Params().setSql(sql).setSelect(true).setResultType(resultClass).setReturnCollection(isReturnCollection);
|
||||
} else if (method.isAnnotationPresent(Insert.class)) {
|
||||
// 新增
|
||||
Insert insert = method.getAnnotation(Insert.class);
|
||||
String sql = insert.value();
|
||||
if (StringUtil.isEmpty(sql)) {
|
||||
throw new RuntimeException(String.format("%s sql不能为空!", sign));
|
||||
}
|
||||
params = new Params().setSql(sql).setInsert(true).setResultType(resultClass);
|
||||
} else if (method.isAnnotationPresent(Delete.class)) {
|
||||
// 删除
|
||||
Delete delete = method.getAnnotation(Delete.class);
|
||||
String sql = delete.value();
|
||||
if (StringUtil.isEmpty(sql)) {
|
||||
throw new RuntimeException(String.format("%s sql不能为空!", sign));
|
||||
}
|
||||
params = new Params().setSql(sql).setDelete(true).setResultType(resultClass);
|
||||
} else if (method.isAnnotationPresent(Update.class)) {
|
||||
// 更新
|
||||
Update update = method.getAnnotation(Update.class);
|
||||
String sql = update.value();
|
||||
if (StringUtil.isEmpty(sql)) {
|
||||
throw new RuntimeException(String.format("%s sql不能为空!", sign));
|
||||
}
|
||||
params = new Params().setSql(sql).setUpdate(true).setResultType(resultClass);
|
||||
}
|
||||
if (null == params) {
|
||||
throw new RuntimeException(String.format("%s 缺失SQL注解!", sign));
|
||||
}
|
||||
if (null == params.getResultType() && !Collection.class.isAssignableFrom(method.getReturnType())) {
|
||||
params.setResultType(method.getReturnType());
|
||||
}
|
||||
paramsCache.set(method, params);
|
||||
},
|
||||
() -> paramsCache.get(method)
|
||||
);
|
||||
}
|
||||
|
||||
@Accessors(chain = true)
|
||||
@Data
|
||||
static class Params {
|
||||
private String sql;
|
||||
private Class<?> resultType;
|
||||
private boolean isReturnCollection;
|
||||
private boolean isSelect;
|
||||
private boolean isDelete;
|
||||
private boolean isUpdate;
|
||||
private boolean isInsert;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.db.mapper;
|
||||
|
||||
/**
|
||||
* sql操作类型
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/8/3
|
||||
*/
|
||||
public enum SqlOperatorType {
|
||||
SELECT,DELETE,UPDATE,INSERT
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* Copyright (c) 2022 aoshiguchen
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package fun.asgc.neutrino.core.db.mapper;
|
||||
|
||||
import fun.asgc.neutrino.core.cache.Cache;
|
||||
import fun.asgc.neutrino.core.cache.MemoryCache;
|
||||
import fun.asgc.neutrino.core.db.annotation.*;
|
||||
import fun.asgc.neutrino.core.util.LockUtil;
|
||||
import fun.asgc.neutrino.core.util.StringUtil;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* sql解析器
|
||||
* @author: aoshiguchen
|
||||
* @date: 2022/8/3
|
||||
*/
|
||||
@Data
|
||||
@Slf4j
|
||||
public class SqlParser {
|
||||
/**
|
||||
* sqlParser实例缓存
|
||||
*/
|
||||
private static final Cache<Method, SqlParser> sqlParserCache = new MemoryCache<>();
|
||||
/**
|
||||
* 目标执行方法
|
||||
*/
|
||||
private Method targetMethod;
|
||||
/**
|
||||
* 操作类型
|
||||
*/
|
||||
private SqlOperatorType operatorType;
|
||||
/**
|
||||
* 结果类型
|
||||
*/
|
||||
private Class<?> resultType;
|
||||
/**
|
||||
* 返回结果组成类型(集合类型的子类型)
|
||||
*/
|
||||
private Class<?> resultComponentType;
|
||||
/**
|
||||
* 目标方法签名
|
||||
*/
|
||||
private String targetMethodSign;
|
||||
/**
|
||||
* 返回数据是否是集合类型
|
||||
*/
|
||||
private boolean isReturnCollection;
|
||||
/**
|
||||
* sql语句
|
||||
*/
|
||||
private String sql;
|
||||
|
||||
private SqlParser(Method targetMethod) {
|
||||
this.targetMethod = targetMethod;
|
||||
this.resultType = targetMethod.getReturnType();
|
||||
this.targetMethodSign = String.format("%s#%s", targetMethod.getDeclaringClass().getName(), targetMethod.getName());
|
||||
this.initByAnnotation();
|
||||
this.initByXml();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据注解进行初始化
|
||||
*/
|
||||
private void initByAnnotation() {
|
||||
if (!StringUtil.isEmpty(this.sql)) {
|
||||
return;
|
||||
}
|
||||
ResultType resultType = targetMethod.getAnnotation(ResultType.class);
|
||||
Class<?> resultClass = (null == resultType) ? null : resultType.value();
|
||||
this.resultComponentType = resultClass;
|
||||
|
||||
if (targetMethod.isAnnotationPresent(Select.class)) {
|
||||
// 查询
|
||||
this.operatorType = SqlOperatorType.SELECT;
|
||||
Select select = targetMethod.getAnnotation(Select.class);
|
||||
this.sql = select.value();
|
||||
if (StringUtil.isEmpty(sql)) {
|
||||
throw new RuntimeException(String.format("%s sql不能为空!", targetMethod));
|
||||
}
|
||||
this.isReturnCollection = Collection.class.isAssignableFrom(targetMethod.getReturnType());
|
||||
if (isReturnCollection && null == resultClass) {
|
||||
throw new RuntimeException(String.format("%s 请指名实体类型!", targetMethodSign));
|
||||
}
|
||||
} else if (targetMethod.isAnnotationPresent(Insert.class)) {
|
||||
// 新增
|
||||
this.operatorType = SqlOperatorType.INSERT;
|
||||
Insert insert = targetMethod.getAnnotation(Insert.class);
|
||||
this.sql = insert.value();
|
||||
if (StringUtil.isEmpty(sql)) {
|
||||
throw new RuntimeException(String.format("%s sql不能为空!", targetMethodSign));
|
||||
}
|
||||
} else if (targetMethod.isAnnotationPresent(Delete.class)) {
|
||||
// 删除
|
||||
this.operatorType = SqlOperatorType.DELETE;
|
||||
Delete delete = targetMethod.getAnnotation(Delete.class);
|
||||
this.sql = delete.value();
|
||||
if (StringUtil.isEmpty(sql)) {
|
||||
throw new RuntimeException(String.format("%s sql不能为空!", targetMethodSign));
|
||||
}
|
||||
} else if (targetMethod.isAnnotationPresent(Update.class)) {
|
||||
// 更新
|
||||
this.operatorType = SqlOperatorType.UPDATE;
|
||||
Update update = targetMethod.getAnnotation(Update.class);
|
||||
this.sql = update.value();
|
||||
if (StringUtil.isEmpty(sql)) {
|
||||
throw new RuntimeException(String.format("%s sql不能为空!", targetMethodSign));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据xml文件进行初始化
|
||||
*/
|
||||
private void initByXml() {
|
||||
if (!StringUtil.isEmpty(this.sql)) {
|
||||
return;
|
||||
}
|
||||
// TODO
|
||||
}
|
||||
|
||||
public static SqlParser getInstance(Method targetMethod) throws Exception {
|
||||
return LockUtil.doubleCheckProcess(
|
||||
() -> !sqlParserCache.containsKey(targetMethod),
|
||||
targetMethod,
|
||||
() -> sqlParserCache.set(targetMethod, new SqlParser(targetMethod)),
|
||||
() -> sqlParserCache.get(targetMethod)
|
||||
);
|
||||
}
|
||||
|
||||
public boolean isSelect() {
|
||||
return this.operatorType == SqlOperatorType.SELECT;
|
||||
}
|
||||
|
||||
public boolean isUpdate() {
|
||||
return this.operatorType == SqlOperatorType.UPDATE;
|
||||
}
|
||||
|
||||
public boolean isDelete() {
|
||||
return this.operatorType == SqlOperatorType.DELETE;
|
||||
}
|
||||
|
||||
public boolean isInsert() {
|
||||
return this.operatorType == SqlOperatorType.INSERT;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user