From 1b421190855d23dcecfa3f762eb330d9bc7f5276 Mon Sep 17 00:00:00 2001 From: aoshiguchen <1052045476@qq.com> Date: Wed, 3 Aug 2022 20:56:32 +0800 Subject: [PATCH] =?UTF-8?q?SqlMapper=E9=80=BB=E8=BE=91=E4=BC=98=E5=8C=96?= =?UTF-8?q?=EF=BC=8Csql=E8=A7=A3=E6=9E=90=E9=80=BB=E8=BE=91=E5=88=86?= =?UTF-8?q?=E7=A6=BB=E5=88=B0SqlParser=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/db/mapper/SqlMapperInterceptor.java | 102 +---------- .../core/db/mapper/SqlOperatorType.java | 31 ++++ .../neutrino/core/db/mapper/SqlParser.java | 168 ++++++++++++++++++ 3 files changed, 208 insertions(+), 93 deletions(-) create mode 100644 neutrino-core/src/main/java/fun/asgc/neutrino/core/db/mapper/SqlOperatorType.java create mode 100644 neutrino-core/src/main/java/fun/asgc/neutrino/core/db/mapper/SqlParser.java diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/mapper/SqlMapperInterceptor.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/mapper/SqlMapperInterceptor.java index d6063fbf..01cfd5df 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/mapper/SqlMapperInterceptor.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/mapper/SqlMapperInterceptor.java @@ -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 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; - } } diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/mapper/SqlOperatorType.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/mapper/SqlOperatorType.java new file mode 100644 index 00000000..35b0ef57 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/mapper/SqlOperatorType.java @@ -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 +} diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/mapper/SqlParser.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/mapper/SqlParser.java new file mode 100644 index 00000000..ff4bde84 --- /dev/null +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/db/mapper/SqlParser.java @@ -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 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; + } +}