diff --git a/neutrino-proxy-server/pom.xml b/neutrino-proxy-server/pom.xml index ce418d11..d224271a 100644 --- a/neutrino-proxy-server/pom.xml +++ b/neutrino-proxy-server/pom.xml @@ -18,6 +18,7 @@ org.noear solon-api + 2.2.1 org.noear @@ -42,7 +43,11 @@ system ${project.basedir}/../_solon_plugin/orika-solon-plugin/pom.xml - + + + + + fun.asgc.neutrino neutrino-proxy-core diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/DBInitialize.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/DBInitialize.java index 984493b9..e8453c83 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/DBInitialize.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/DBInitialize.java @@ -22,15 +22,20 @@ package fun.asgc.neutrino.proxy.server.base.db; import com.google.common.collect.Lists; -import fun.asgc.neutrino.core.db.template.JdbcTemplate; -import fun.asgc.neutrino.core.util.*; +import fun.asgc.neutrino.core.util.Assert; +import fun.asgc.neutrino.core.util.CollectionUtil; +import fun.asgc.neutrino.core.util.FileUtil; +import fun.asgc.neutrino.core.util.StringUtil; +import fun.asgc.neutrino.proxy.server.base.db.template.JdbcTemplate; import fun.asgc.neutrino.proxy.server.base.rest.config.DbConfig; import fun.asgc.neutrino.proxy.server.constant.DbTypeEnum; import lombok.extern.slf4j.Slf4j; import org.noear.solon.annotation.Component; +import org.noear.solon.annotation.Init; import org.noear.solon.annotation.Inject; import org.noear.solon.core.event.AppLoadEndEvent; import org.noear.solon.core.event.EventListener; + import java.util.List; /** @@ -46,11 +51,10 @@ public class DBInitialize implements EventListener { private DbConfig dbConfig; @Inject private JdbcTemplate jdbcTemplate; - private DbTypeEnum dbTypeEnum; - @Override - public void onEvent(AppLoadEndEvent appLoadEndEvent) throws Throwable { + @Init + public void init() throws Throwable { Assert.notNull(dbConfig.getType(), "neutrino.data.db.type不能为空!"); dbTypeEnum = DbTypeEnum.of(dbConfig.getType()); Assert.notNull(dbTypeEnum, "neutrino.data.db.type取值异常!"); @@ -60,6 +64,11 @@ public class DBInitialize implements EventListener { initDBData(); } + @Override + public void onEvent(AppLoadEndEvent appLoadEndEvent) throws Throwable { + // TODO 该事件有50%的概率不触发 + } + /** * 初始化数据库结构 */ @@ -92,6 +101,7 @@ public class DBInitialize implements EventListener { } for (String tableName : initDataTableNameList) { // 表里没有数据的时候,才进行初始化操作 + int count = jdbcTemplate.queryForInt(String.format("select count(1) from `%s`", tableName)); if (count > 0) { continue; @@ -114,43 +124,4 @@ public class DBInitialize implements EventListener { } } } - -// /** -// * 获取jdbcTemplate实例 -// * @return -// * @throws Exception -// */ -// private JdbcTemplate getJdbcTemplate() throws Exception { -// return LockUtil.doubleCheckProcess( -// () -> null == jdbcTemplate, -// DBInitialize2.class, -// () -> { -// if (DbTypeEnum.SQLITE == dbTypeEnum) { -// //建立一个数据库名data.db的连接,如果不存在就在当前目录下创建之 -// DriverManager.getConnection(dbConfig.getUrl()); -// // 创建数据源 -// SQLiteDataSource dataSource = new SQLiteDataSource(); -// dataSource.setUrl(dbConfig.getUrl()); -// dataSource.setJournalMode(SQLiteConfig.JournalMode.WAL.getValue()); -// // 创建jdbcTemplate -// jdbcTemplate = new JdbcTemplate(dataSource); -// } else if (DbTypeEnum.MYSQL == dbTypeEnum) { -// DruidDataSource dataSource = new DruidDataSource(); -// dataSource.setDriverClassName(dbConfig.getDriverClass()); -// dataSource.setUrl(dbConfig.getUrl()); -// dataSource.setInitialSize(5); -// dataSource.setMinIdle(5); -// dataSource.setMaxActive(20); -// dataSource.setMaxWait(60000); -// dataSource.setPoolPreparedStatements(true); -// dataSource.setUsername(dbConfig.getUsername()); -// dataSource.setPassword(dbConfig.getPassword()); -// -// // 创建jdbcTemplate -// jdbcTemplate = new JdbcTemplate(dataSource); -// } -// }, -// () -> jdbcTemplate -// ); -// } } diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/DbConfiguration.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/DbConfiguration.java index ddf3a7ba..c9ed500c 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/DbConfiguration.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/DbConfiguration.java @@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder; import com.baomidou.mybatisplus.core.config.GlobalConfig; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; -import fun.asgc.neutrino.core.db.template.JdbcTemplate; +import fun.asgc.neutrino.proxy.server.base.db.template.JdbcTemplate; import fun.asgc.neutrino.proxy.server.base.rest.config.DbConfig; import fun.asgc.neutrino.proxy.server.constant.DbTypeEnum; import org.apache.ibatis.solon.annotation.Db; diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/SqlMapperInterceptor.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/SqlMapperInterceptor.java index 0ea54051..b9035d42 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/SqlMapperInterceptor.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/SqlMapperInterceptor.java @@ -28,11 +28,11 @@ import fun.asgc.neutrino.core.aop.Invocation; import fun.asgc.neutrino.core.aop.interceptor.Interceptor; import fun.asgc.neutrino.core.db.mapper.SqlParser; import fun.asgc.neutrino.core.db.page.PageInfo; -import fun.asgc.neutrino.core.db.template.JdbcTemplate; import fun.asgc.neutrino.core.util.ArrayUtil; import fun.asgc.neutrino.core.util.Assert; import fun.asgc.neutrino.core.util.StringUtil; import fun.asgc.neutrino.core.util.TypeUtil; +import fun.asgc.neutrino.proxy.server.base.db.template.JdbcTemplate; import org.noear.solon.Solon; import java.lang.reflect.Parameter; diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/DataSourceHolder.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/DataSourceHolder.java new file mode 100644 index 00000000..2d0dd46c --- /dev/null +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/DataSourceHolder.java @@ -0,0 +1,86 @@ +/** + * 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.proxy.server.base.db.template; + +import fun.asgc.neutrino.core.db.dao.DBType; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +/** + * 数据源持有者 + * @author: aoshiguchen + * @date: 2022/6/28 + */ +public class DataSourceHolder { + /** + * 数据源 + */ + private DataSource dataSource; + /** + * 是否保持连接 + * 默认执行完SQL操作就归还连接 + * 在开启事务的情况下,事务操作完毕才能归还 + */ + private ThreadLocal keepConnectionCache = new ThreadLocal<>(); + /** + * 数据库类型 + */ + private DBType dbType; + + public DataSourceHolder(DataSource dataSource) { + this.dataSource = dataSource; + } + + public DataSourceHolder(DataSource dataSource, DBType dbType) { + this.dataSource = dataSource; + this.dbType = dbType; + } + + public Connection getConnection() throws SQLException { + return this.dataSource.getConnection(); + } + + public void close(Connection conn) throws SQLException { + conn.close(); + } + + public void tryClose(Connection conn) throws SQLException { + Boolean keepConnection = keepConnectionCache.get(); + if (null == keepConnection || !keepConnection) { + conn.close(); + } + } + + public void setKeepConnection(Boolean keepConnection) { + this.keepConnectionCache.set(keepConnection); + } + + public DBType getDbType() { + return dbType; + } + + public void setDbType(DBType dbType) { + this.dbType = dbType; + } +} diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/DbCache.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/DbCache.java new file mode 100644 index 00000000..bddb181e --- /dev/null +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/DbCache.java @@ -0,0 +1,281 @@ +/** + * 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.proxy.server.base.db.template; + +import com.google.common.collect.Lists; +import fun.asgc.neutrino.core.cache.Cache; +import fun.asgc.neutrino.core.cache.MemoryCache; +import fun.asgc.neutrino.core.cache.MemoryCacheGroup; +import fun.asgc.neutrino.core.db.annotation.Column; +import fun.asgc.neutrino.core.db.annotation.NotColumn; +import fun.asgc.neutrino.core.db.annotation.Table; +import fun.asgc.neutrino.core.util.*; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Set; + +/** + * 数据库相关缓存 + * @author: aoshiguchen + * @date: 2022/6/27 + */ +public class DbCache { + /** + * 名称映射缓存组 + */ + private static final MemoryCacheGroup nameMappingCache = new MemoryCacheGroup<>(); + private static final String GROUP_COLUMN_NAME_TO = "GROUP_COLUMN_NAME_TO"; + private static final String GROUP_COLUMN_NAME_FROM = "GROUP_COLUMN_NAME_FROM"; + private static final String GROUP_TABLE_NAME_TO = "GROUP_TABLE_NAME_TO"; + private static final String GROUP_TABLE_NAME_FROM = "GROUP_TABLE_NAME_FROM"; + private static final Cache, Cache> fieldToColumnCache = new MemoryCache<>(); + private static final Object fieldToColumnCacheLock = new Object(); + private static final Cache,String> classTableNameCache = new MemoryCache<>(); + + /** + * 转换为列名 + * @param s + * @return + */ + public static String toColumnName(String s) { + try { + return LockUtil.doubleCheckProcess( + () -> !nameMappingCache.containsKey(GROUP_COLUMN_NAME_TO, s), + GROUP_COLUMN_NAME_TO, + () -> nameMappingCache.set(GROUP_COLUMN_NAME_TO, s, DefaultColumnNameConvert.getInstance().to(s)), + () -> nameMappingCache.get(GROUP_COLUMN_NAME_TO, s) + ); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 转换为字段名 + * @param s + * @return + */ + public static String fromColumnName(String s) { + try { + return LockUtil.doubleCheckProcess( + () -> !nameMappingCache.containsKey(GROUP_COLUMN_NAME_FROM, s), + GROUP_COLUMN_NAME_FROM, + () -> nameMappingCache.set(GROUP_COLUMN_NAME_FROM, s, DefaultColumnNameConvert.getInstance().from(s)), + () -> nameMappingCache.get(GROUP_COLUMN_NAME_FROM, s) + ); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 转换为表名 + * @param s + * @return + */ + public static String toTableName(String s) { + try { + return LockUtil.doubleCheckProcess( + () -> !nameMappingCache.containsKey(GROUP_TABLE_NAME_TO, s), + GROUP_TABLE_NAME_TO, + () -> nameMappingCache.set(GROUP_TABLE_NAME_TO, s, DefaultTableNameConvert.getInstance().to(s)), + () -> nameMappingCache.get(GROUP_TABLE_NAME_TO, s) + ); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 转换为表名 + * @param clazz + * @return + */ + public static String toTableName(Class> clazz) { + try { + return LockUtil.doubleCheckProcess(() -> !classTableNameCache.containsKey(clazz), + clazz, + () -> { + Table table = clazz.getAnnotation(Table.class); + String tableName; + if (null != table && StringUtil.notEmpty(table.value())) { + tableName = table.value(); + } else { + tableName = toTableName(TypeUtil.getSimpleName(clazz)); + } + classTableNameCache.set(clazz, tableName); + }, + () -> classTableNameCache.get(clazz) + ); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 转换为实体名 + * @param s + * @return + */ + public static String fromTableName(String s) { + try { + return LockUtil.doubleCheckProcess( + () -> !nameMappingCache.containsKey(GROUP_TABLE_NAME_FROM, s), + GROUP_TABLE_NAME_FROM, + () -> nameMappingCache.set(GROUP_TABLE_NAME_FROM, s, DefaultTableNameConvert.getInstance().from(s)), + () -> nameMappingCache.get(GROUP_TABLE_NAME_FROM, s) + ); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 根据类+列名获取字段 + * @param clazz + * @param column + * @return + */ + public static List getField(Class> clazz, String column) { + try { + return LockUtil.doubleCheckProcess( + () -> !fieldToColumnCache.containsKey(clazz), + fieldToColumnCacheLock, + () -> initFieldCache(clazz), + () -> { + List list = Lists.newArrayList(); + Cache cache = fieldToColumnCache.get(clazz); + if (null == cache || cache.isEmpty()) { + return list; + } + for (Field field : cache.keySet()) { + if (cache.get(field).equals(column)) { + list.add(field); + } + } + + return list; + } + ); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 根据类名获取列名列表 + * @param clazz + * @return + */ + public static List getFieldList(Class> clazz) { + try { + return LockUtil.doubleCheckProcess( + () -> !fieldToColumnCache.containsKey(clazz), + fieldToColumnCacheLock, + () -> initFieldCache(clazz), + () -> { + List list = Lists.newArrayList(); + Cache cache = fieldToColumnCache.get(clazz); + if (null == cache || cache.isEmpty()) { + return list; + } + list.addAll(cache.keySet()); + return list; + } + ); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 根据类获取字段缓存 + * @param clazz + * @return + */ + public static Cache getFieldCache(Class> clazz) { + try { + return LockUtil.doubleCheckProcess( + () -> !fieldToColumnCache.containsKey(clazz), + clazz, + () -> initFieldCache(clazz), + () -> fieldToColumnCache.get(clazz) + ); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static String getColumnNameByField(Field field) { + try { + return LockUtil.doubleCheckProcess( + () -> !fieldToColumnCache.containsKey(field.getDeclaringClass()), + fieldToColumnCacheLock, + () -> initFieldCache(field.getDeclaringClass()), + () -> { + if (!fieldToColumnCache.containsKey(field.getDeclaringClass()) || !fieldToColumnCache.get(field.getDeclaringClass()).containsKey(field)) { + return null; + } + return fieldToColumnCache.get(field.getDeclaringClass()).get(field); + } + ); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 初始化字段缓存 + * @param clazz + */ + private static void initFieldCache(Class> clazz) { + Set fieldSet = ReflectUtil.getDeclaredFields(clazz); + if (CollectionUtil.isEmpty(fieldSet)) { + return; + } + Cache cache = new MemoryCache<>(); + fieldSet.forEach(field -> { + if (field.isAnnotationPresent(NotColumn.class)) { + return; + } + Column column = field.getAnnotation(Column.class); + if (null != column && StringUtil.notEmpty(column.value())) { + cache.set(field, column.value()); + } else { + cache.set(field, toColumnName(field.getName())); + } + + }); + + fieldToColumnCache.set(clazz, cache); + } +} diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/DefaultColumnNameConvert.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/DefaultColumnNameConvert.java new file mode 100644 index 00000000..a8056c41 --- /dev/null +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/DefaultColumnNameConvert.java @@ -0,0 +1,89 @@ +/** + * 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.proxy.server.base.db.template; + +import fun.asgc.neutrino.core.base.Convert; +import fun.asgc.neutrino.core.util.StringUtil; + +/** + * 默认的列名转换器转换器 + * 代码 -> DB + * @author: aoshiguchen + * @date: 2022/6/27 + */ +public class DefaultColumnNameConvert implements Convert { + private static final DefaultColumnNameConvert instance = new DefaultColumnNameConvert(); + private static final char SEPARATOR = '_'; + + private DefaultColumnNameConvert() { + + } + + public static DefaultColumnNameConvert getInstance() { + return instance; + } + + @Override + public String from(String target) { + if (StringUtil.isEmpty(target)) { + return ""; + } + boolean flag = false; + StringBuilder sb = new StringBuilder(target.length()); + for (char c : target.toCharArray()) { + if (SEPARATOR == c) { + flag = true; + } else { + if (flag) { + sb.append(Character.toUpperCase(c)); + flag = false; + } else { + sb.append(c); + } + } + } + return sb.toString(); + } + + @Override + public String to(String source) { + if (StringUtil.isEmpty(source)) { + return ""; + } + boolean flag = true; + StringBuilder sb = new StringBuilder(source.length()); + for (char c : source.toCharArray()) { + if (flag) { + sb.append(Character.toLowerCase(c)); + flag = false; + } else { + if (Character.isUpperCase(c)) { + sb.append(SEPARATOR); + sb.append(Character.toLowerCase(c)); + } else { + sb.append(c); + } + } + } + return sb.toString(); + } +} diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/DefaultTableNameConvert.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/DefaultTableNameConvert.java new file mode 100644 index 00000000..35285b06 --- /dev/null +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/DefaultTableNameConvert.java @@ -0,0 +1,88 @@ +/** + * 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.proxy.server.base.db.template; + +import fun.asgc.neutrino.core.base.Convert; +import fun.asgc.neutrino.core.util.StringUtil; + +/** + * + * @author: aoshiguchen + * @date: 2022/6/27 + */ +public class DefaultTableNameConvert implements Convert { + private static final DefaultTableNameConvert instance = new DefaultTableNameConvert(); + private static final char SEPARATOR = '_'; + + private DefaultTableNameConvert() { + + } + + public static DefaultTableNameConvert getInstance() { + return instance; + } + + @Override + public String from(String target) { + if (StringUtil.isEmpty(target)) { + return ""; + } + boolean flag = true; + StringBuilder sb = new StringBuilder(target.length()); + for (char c : target.toCharArray()) { + if (SEPARATOR == c) { + flag = true; + } else { + if (flag) { + sb.append(Character.toUpperCase(c)); + flag = false; + } else { + sb.append(c); + } + } + } + return sb.toString(); + } + + @Override + public String to(String source) { + if (StringUtil.isEmpty(source)) { + return ""; + } + boolean flag = true; + StringBuilder sb = new StringBuilder(source.length()); + for (char c : source.toCharArray()) { + if (flag) { + sb.append(Character.toLowerCase(c)); + flag = false; + } else { + if (Character.isUpperCase(c)) { + sb.append(SEPARATOR); + sb.append(Character.toLowerCase(c)); + } else { + sb.append(c); + } + } + } + return sb.toString(); + } +} diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/JdbcCallback.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/JdbcCallback.java new file mode 100644 index 00000000..0ebd8dcd --- /dev/null +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/JdbcCallback.java @@ -0,0 +1,38 @@ +/** + * 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.proxy.server.base.db.template; + +import java.sql.SQLException; + +/** + * @author: aoshiguchen + * @date: 2022/6/27 + */ +public interface JdbcCallback { + + /** + * 执行 + * @return + */ + T execute() throws SQLException; + +} diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/JdbcOperations.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/JdbcOperations.java new file mode 100644 index 00000000..8cb366b7 --- /dev/null +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/JdbcOperations.java @@ -0,0 +1,293 @@ +/** + * 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.proxy.server.base.db.template; + +import fun.asgc.neutrino.core.db.annotation.Id; +import fun.asgc.neutrino.core.util.CollectionUtil; +import fun.asgc.neutrino.core.util.ReflectUtil; +import fun.asgc.neutrino.core.util.TypeUtil; + +import java.lang.reflect.Field; +import java.sql.*; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * + * @author: aoshiguchen + * @date: 2022/6/27 + */ +public class JdbcOperations { + private static final JdbcOperations instance = new JdbcOperations(); + + private static final Map, Field> generateIdFieldMap = new ConcurrentHashMap<>(); + + private JdbcOperations() { + + } + + public static JdbcOperations getInstance() { + return instance; + } + + /** + * 通用执行方法 + * @param callback + * @param + * @return + */ + public T execute(JdbcCallback callback) throws SQLException { + return callback.execute(); + } + + /** + * 执行更新操作 + * @param conn + * @param sql + * @param params + * @return + */ + public int executeUpdate(final Connection conn , final String sql, final Object[] params) throws SQLException { + return this.execute(new PreparedStatementJdbcCallback(){ + @Override + public Integer execute(PreparedStatement ps) throws SQLException { + return ps.executeUpdate(); + } + @Override + public Object[] getParams() { + return params; + } + @Override + public String getSql() { + return sql; + } + @Override + public Connection getConnection(){ + return conn; + } + }); + } + + /** + * 执行更新操作 + * 临时兼容返设主键问题 + * @param conn + * @param sql + * @param params + * @return + */ + public int executeUpdateByModel(final Connection conn , final String sql, final Object model, final Object[] params) throws SQLException { + return this.execute(new PreparedStatementJdbcCallback(){ + @Override + public Integer execute(PreparedStatement ps) throws SQLException { + Integer res = ps.executeUpdate(); + if (null != model) { + ResultSet resultSet = ps.getGeneratedKeys(); + if (resultSet.next()) { + Field field = getGenerateIdField(model.getClass()); + if (null != field) { + ReflectUtil.setFieldValue(field, model, resultSet.getInt(1)); + } + } + } + return res; + } + @Override + public Object[] getParams() { + return params; + } + @Override + public String getSql() { + return sql; + } + @Override + public Connection getConnection(){ + return conn; + } + }); + } + + /** + * 执行单条查询操作 + * @param conn + * @param clazz + * @param sql + * @param params + * @param + * @return + */ + public T executeQuery(final Connection conn,final Class clazz,final String sql,final Object[] params) throws SQLException { + return this.execute(new PreparedStatementJdbcCallback() { + + @Override + public T execute(PreparedStatement ps) { + T obj = null; + + try{ + ResultSet resultSet = ps.executeQuery(); + if(resultSet.next()){ + if(TypeUtil.isNormalBasicType(clazz)){ + Object value = resultSet.getObject(1); + obj = TypeUtil.conversion(value, clazz); + }else if(TypeUtil.isMap(clazz)){ + Map map = new HashMap(); + obj = (T)map; + + ResultSetMetaData rsmd = resultSet.getMetaData(); + int columnCount = rsmd.getColumnCount(); + for(int i = 1;i <= columnCount;i++){ + String name = rsmd.getColumnName(i); + Object value = resultSet.getObject(i); + map.put(DbCache.fromColumnName(name), value); + } + }else{ + obj = clazz.newInstance(); + ResultSetMetaData rsmd = resultSet.getMetaData(); + int columnCount = rsmd.getColumnCount(); + for(int i = 1;i <= columnCount;i++){ + String name = rsmd.getColumnName(i); + Object value = resultSet.getObject(i); + List fieldList = DbCache.getField(clazz, name); + ReflectUtil.setFieldValue(fieldList, obj, value); + } + } + } + }catch(Exception e){ + throw new RuntimeException(e); + } + return obj; + } + @Override + public Connection getConnection() { + return conn; + } + @Override + public Object[] getParams() { + return params; + } + @Override + public String getSql() { + return sql; + } + }); + } + + /** + * 执行多条查询操作 + * @param conn + * @param clazz + * @param sql + * @param params + * @param + * @return + */ + public List executeQueryForList(final Connection conn, final Class clazz, final String sql, final Object[] params) throws SQLException { + return this.execute(new PreparedStatementJdbcCallback>() { + @Override + public List execute(PreparedStatement ps) { + List res = new ArrayList(); + try{ + ResultSet resultSet = ps.executeQuery(); + ResultSetMetaData rsmd = resultSet.getMetaData(); + int columnCount = rsmd.getColumnCount(); + + while(resultSet.next()){ + T obj = null; + + if(TypeUtil.isNormalBasicType(clazz)){ + Object value = resultSet.getObject(1); + obj = TypeUtil.conversion(value, clazz); + }else if(TypeUtil.isMap(clazz)){ + Map map = new HashMap(); + obj = (T)map; + + for(int i = 1;i <= columnCount;i++){ + String name = rsmd.getColumnName(i); + Object value = resultSet.getObject(i); + map.put(DbCache.fromColumnName(name), value); + } + }else{ + obj = clazz.newInstance(); + + for(int i = 1;i <= columnCount;i++){ + String name = rsmd.getColumnName(i); + Object value = resultSet.getObject(i); + List fieldList = DbCache.getField(clazz, name); + ReflectUtil.setFieldValue(fieldList, obj, value); + } + } + + res.add(obj); + } + + }catch(Exception e){ + throw new RuntimeException(e); + } + + return res; + } + + @Override + public Connection getConnection() { + + return conn; + } + + @Override + public Object[] getParams() { + + return params; + } + + @Override + public String getSql() { + + return sql; + } + + }); + } + + /** + * 获取自动生成ID字段 + * @param clazz + * @return + */ + private static Field getGenerateIdField(Class> clazz) { + if (null == clazz) { + return null; + } + if (generateIdFieldMap.containsKey(clazz)) { + return generateIdFieldMap.get(clazz); + } + Set fields = ReflectUtil.getDeclaredFields(clazz); + if (CollectionUtil.isEmpty(fields)) { + return null; + } + Field field = fields.stream().filter(f -> f.isAnnotationPresent(Id.class)).findFirst().orElse(null); + if (null != field) { + return field; + } + field = fields.stream().filter(f -> f.getName().equals("id")).findFirst().orElse(null); + return field; + } +} diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/JdbcTemplate.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/JdbcTemplate.java new file mode 100644 index 00000000..0c11d5ef --- /dev/null +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/JdbcTemplate.java @@ -0,0 +1,452 @@ +/** + * 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.proxy.server.base.db.template; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * + * @author: aoshiguchen + * @date: 2022/6/27 + */ +public class JdbcTemplate { + /** + * 数据源持有者 + */ + private DataSourceHolder dataSourceHolder; + /** + * jdbc操作 + */ + private JdbcOperations jdbcOperations; + + public JdbcTemplate(DataSource dataSource) { + this(new DataSourceHolder(dataSource)); + } + + public JdbcTemplate(DataSourceHolder dataSourceHolder) { + this.dataSourceHolder = dataSourceHolder; + this.jdbcOperations = JdbcOperations.getInstance(); + } + + public int update(String sql, Object ...params) throws SQLException { + int res = -1; + Connection conn = null; + + try { + conn = dataSourceHolder.getConnection(); + res = jdbcOperations.executeUpdate(conn,sql, params); + } finally { + try { + dataSourceHolder.tryClose(conn); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + return res; + } + + /** + * TODO 临时用来兼容insert之后需要返设主键的问题 + * @param sql + * @param params + * @return + * @throws SQLException + */ + public int updateByModel(String sql, Object model, Object ...params) throws SQLException { + int res = -1; + Connection conn = null; + + try { + conn = dataSourceHolder.getConnection(); + res = jdbcOperations.executeUpdateByModel(conn,sql, model, params); + } finally { + try { + dataSourceHolder.tryClose(conn); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + return res; + } + + public int update(SqlAndParams sqlAndParams) throws SQLException { + return update(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public int updateByMap(String sql, Map params) throws SQLException { + return update(new SqlAndParams(sql, params)); + } + + public int updateByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return updateByModel(sqlAndParams.getSql(), model, sqlAndParams.getParamArray()); + } + + public T query(Class clazz, String sql, Object ...params) throws SQLException { + T res = null; + Connection conn = null; + try { + conn = dataSourceHolder.getConnection(); + res = jdbcOperations.executeQuery(conn, clazz,sql, params); + } finally { + try { + dataSourceHolder.tryClose(conn); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + return res; + } + + public T query(Class clazz, SqlAndParams sqlAndParams) throws SQLException { + return query(clazz, sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public T queryByMap(Class clazz, String sql, Map params) throws SQLException { + return query(clazz, new SqlAndParams(sql, params)); + } + + public T queryByModel(Class clazz, String sql, Object model) throws SQLException { + return query(clazz, new SqlAndParams(sql, model)); + } + + public byte queryForByteByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForByte(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public byte queryForByteByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForByte(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public byte queryForByte(String sql, Object ...params) throws SQLException { + return query(byte.class, sql, params); + } + + public short queryForShortByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForShort(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public short queryForShortByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForShort(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public short queryForShort(String sql, Object ...params) throws SQLException { + return query(short.class, sql, params); + } + + public int queryForIntByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForInt(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public int queryForIntByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForInt(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public int queryForInt(String sql, Object ...params) throws SQLException { + return query(int.class, sql, params); + } + + public Long queryForLongByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForLong(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public Long queryForLongByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForLong(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public Long queryForLong(String sql,Object ...params) throws SQLException { + return query(long.class, sql, params); + } + + public float queryForFloatByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForFloat(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public float queryForFloatByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForFloat(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public float queryForFloat(String sql,Object ...params) throws SQLException { + return query(float.class, sql, params); + } + + public double queryForDoubleByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForDouble(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public double queryForDoubleByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForDouble(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public double queryForDouble(String sql, Object ...params) throws SQLException { + return query(double.class, sql, params); + } + + public char queryForCharByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForChar(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public char queryForCharByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForChar(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public char queryForChar(String sql, Object ...params) throws SQLException { + return query(char.class, sql, params); + } + + public boolean queryForBooleanByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForBoolean(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public boolean queryForBooleanByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForBoolean(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public boolean queryForBoolean(String sql, Object ...params) throws SQLException { + return query(boolean.class, sql, params); + } + + public String queryForStringByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForString(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public String queryForStringByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForString(sql, sqlAndParams.getParamArray()); + } + + public String queryForString(String sql, Object ...params) throws SQLException { + return query(String.class, sql, params); + } + + public Map queryForMapByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForMap(sql, sqlAndParams.getParamArray()); + } + + public Map queryForMapByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForMap(sql, sqlAndParams.getParamArray()); + } + + public Map queryForMap(String sql, Object ...params) throws SQLException { + return (Map)query(HashMap.class, sql, params); + } + + public List queryForList(Class clazz, String sql, Object ...params) throws SQLException { + List res = null; + Connection conn = null; + + try { + conn = dataSourceHolder.getConnection(); + res = jdbcOperations.executeQueryForList(conn, clazz, sql, params); + } finally { + try { + dataSourceHolder.tryClose(conn); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + return res; + } + + public List queryForList(Class clazz, SqlAndParams sqlAndParams) throws SQLException { + return queryForList(clazz, sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListByMap(Class clazz, String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForList(clazz, sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListByModel(Class clazz, String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForList(clazz, sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListByteByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForListByte(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListByteByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForListByte(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListByte(String sql,Object ...params) throws SQLException { + return queryForList(byte.class, sql,params); + } + + public List queryForListShortByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForListShort(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListShortByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForListShort(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListShort(String sql, Object ...params) throws SQLException { + return queryForList(short.class, sql, params); + } + + public List queryForListIntByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForListInt(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListIntByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForListInt(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListInt(String sql, Object ...params) throws SQLException { + return queryForList(int.class, sql, params); + } + + public List queryForListLongByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForListLong(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListLongByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForListLong(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListLong(String sql,Object ...params) throws SQLException { + return queryForList(long.class, sql, params); + } + + public List queryForListFloatByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForListFloat(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListFloatByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForListFloat(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListFloat(String sql, Object ...params) throws SQLException { + return queryForList(float.class, sql, params); + } + + public List queryForListDoubleByMap(String sql ,Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForListDouble(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListDoubleByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForListDouble(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListDouble(String sql, Object ...params) throws SQLException { + return queryForList(double.class, sql, params); + } + + public List queryForListCharByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForListChar(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListCharByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForListChar(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListChar(String sql, Object ...params) throws SQLException { + return queryForList(char.class, sql, params); + } + + public List queryForListBooleanByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForListBoolean(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListBooleanByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForListBoolean(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListBoolean(String sql, Object ...params) throws SQLException { + return queryForList(boolean.class, sql, params); + } + + public List queryForListStringByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForListString(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListStringByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForListString(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListString(String sql, Object ...params) throws SQLException { + return queryForList(String.class, sql, params); + } + + public List queryForListMap(String sql, Object ...params) throws SQLException { + return queryForList(Map.class, sql, params); + } + + public List queryForListMapByMap(String sql, Map params) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, params); + return queryForListMap(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + + public List queryForListMapByModel(String sql, Object model) throws SQLException { + SqlAndParams sqlAndParams = new SqlAndParams(sql, model); + return queryForListMap(sqlAndParams.getSql(), sqlAndParams.getParamArray()); + } + +} diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/PreparedStatementJdbcCallback.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/PreparedStatementJdbcCallback.java new file mode 100644 index 00000000..690d595e --- /dev/null +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/PreparedStatementJdbcCallback.java @@ -0,0 +1,95 @@ +/** + * 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.proxy.server.base.db.template; + +import fun.asgc.neutrino.core.util.ArrayUtil; +import lombok.extern.slf4j.Slf4j; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * + * @author: aoshiguchen + * @date: 2022/6/27 + */ +@Slf4j +public abstract class PreparedStatementJdbcCallback implements JdbcCallback { + + @Override + public T execute() throws SQLException { + PreparedStatement pstm = null; + Object[] params = this.getParams(); + Connection conn = getConnection(); + + T res = null; + + log.debug("sql:" + this.getSql()); + StringBuffer sb = new StringBuffer(); + if (ArrayUtil.notEmpty(params)) { + for (Object o : params) { + sb.append(o).append(","); + } + + if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ',') { + sb.deleteCharAt(sb.length() - 1); + } + } + log.debug("params:" + sb.toString()); + pstm = conn.prepareStatement(this.getSql(), Statement.RETURN_GENERATED_KEYS); + if (ArrayUtil.notEmpty(params)) { + for (int i = 0; i < params.length; i++) { + pstm.setObject(i + 1, params[i]); + } + } + res = this.execute(pstm); + + return res; + } + + /** + * 获取参数 + * @return + */ + abstract Object[] getParams(); + + /** + * 获取sql语句 + * @return + */ + abstract String getSql(); + + /** + * 执行 + * @param ps + * @return + */ + abstract T execute(PreparedStatement ps) throws SQLException; + + /** + * 获取数据库连接 + * @return + */ + abstract Connection getConnection(); +} diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/SqlAndParams.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/SqlAndParams.java new file mode 100644 index 00000000..65d00f45 --- /dev/null +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/SqlAndParams.java @@ -0,0 +1,145 @@ +/** + * 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.proxy.server.base.db.template; + +import fun.asgc.neutrino.core.base.Orderly; +import fun.asgc.neutrino.core.util.ReflectUtil; + +import java.lang.reflect.Field; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * sql语句+sql参数的封装,用于支持以下3种用法 + * 1、jdbcTemplate.query(User.class,"select * from user where id = ?",1); + * 2、dbcTemplate.query(User.class,"select * from user where id = :id", new HashMap(){ + * { + * this.put("id","1"); + * } + * }); + * 3、dbcTemplate.query(User.class,"select * from user where id = :id", new User().setId("1")); + * @author: aoshiguchen + * @date: 2022/6/27 + */ +public class SqlAndParams { + private String sql; + private Object[] paramArray; + private Map paramMap; + private Object paramObject; + + public SqlAndParams(String sql, Object[] paramArray) { + this.sql = sql; + this.paramArray = paramArray; + } + + public SqlAndParams(String sql) { + this.sql = sql; + } + + public SqlAndParams(String sql,Map paramMap) { + this.sql = sql; + this.paramMap = paramMap; + this.initParams(); + } + + public SqlAndParams(String sql,Object paramObject) { + this.sql = sql; + this.paramObject = paramObject; + + this.initParamMap(); + this.initParams(); + } + + private void initParamMap(){ + if (null == paramObject) { + return; + } + if (null == paramMap) { + paramMap = new HashMap<>(); + } + for(Field field : ReflectUtil.getDeclaredFields(paramObject.getClass())){ + paramMap.put(field.getName(), ReflectUtil.getFieldValue(field, paramObject)); + } + } + + private void initParams() { + if (null == paramMap) { + paramMap = new HashMap<>(); + } + String originSql = sql; + List orderlyList = new ArrayList<>(); + for(String key : paramMap.keySet()){ + int index = originSql.indexOf(":" + key); + if(-1 != index){ + List currentList = new ArrayList<>(); + + // 解决数组、集合参数问题 + int count = 1; + Object tmp = paramMap.get(key); + if (null != tmp) { + if (tmp.getClass().isArray()) { + count = ((Object[])tmp).length; + currentList.addAll(Stream.of((Object[])tmp).map(e -> new Orderly(e, index)).collect(Collectors.toList())); + } else if (Collection.class.isAssignableFrom(tmp.getClass())) { + count = ((Collection)tmp).size(); + Object[] arr = ((Collection)tmp).toArray(); + paramMap.put(key, arr); + currentList.addAll((List)((Collection)tmp).stream().map(e -> new Orderly(e, index)).collect(Collectors.toList())); + } + } + List s = new ArrayList<>(); + for (int i = 0; i < count; i++) { + s.add("?"); + } + sql = sql.replaceFirst(":" + key, s.stream().collect(Collectors.joining(","))); + + if (currentList.isEmpty()) { + currentList.add(new Orderly(paramMap.get(key), index)); + } + + orderlyList.addAll(currentList); +// orderlyList.add(new Orderly(paramMap.get(key), index)); + } + } + + this.paramArray = orderlyList.stream().sorted().map(Orderly::getData).collect(Collectors.toList()).toArray(); + } + + public Object[] getParamArray(){ + return paramArray; + } + + public String getSql(){ + return sql; + } + + @Override + public String toString() { + return "SqlAndParams{" + + "sql='" + sql + '\'' + + ", paramArray=" + Arrays.toString(paramArray) + + ", paramMap=" + paramMap + + ", paramObject=" + paramObject + + '}'; + } +} diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/controller/LicenseController.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/controller/LicenseController.java index 08cf1df1..d1ce66c2 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/controller/LicenseController.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/controller/LicenseController.java @@ -21,8 +21,6 @@ */ package fun.asgc.neutrino.proxy.server.controller; -import fun.asgc.neutrino.core.web.annotation.RequestBody; -import fun.asgc.neutrino.core.web.annotation.RequestParam; import fun.asgc.neutrino.proxy.server.base.page.PageInfo; import fun.asgc.neutrino.proxy.server.base.page.PageQuery; import fun.asgc.neutrino.proxy.server.base.rest.annotation.OnlyAdmin; @@ -64,7 +62,7 @@ public class LicenseController { @OnlyAdmin @Post @Mapping("/create") - public LicenseCreateRes create(@RequestBody LicenseCreateReq req) { + public LicenseCreateRes create(LicenseCreateReq req) { ParamCheckUtil.checkNotNull(req, "req"); ParamCheckUtil.checkNotEmpty(req.getName(), "name"); ParamCheckUtil.checkNotNull(req.getUserId(), "userId"); @@ -75,7 +73,7 @@ public class LicenseController { @OnlyAdmin @Post @Mapping("/update") - public LicenseUpdateRes update(@RequestBody LicenseUpdateReq req) { + public LicenseUpdateRes update(LicenseUpdateReq req) { ParamCheckUtil.checkNotNull(req, "req"); ParamCheckUtil.checkNotNull(req.getId(), "id"); ParamCheckUtil.checkNotEmpty(req.getName(), "name"); @@ -85,7 +83,7 @@ public class LicenseController { @Post @Mapping("/detail") - public LicenseDetailRes detail(@RequestParam("id") Integer id) { + public LicenseDetailRes detail(Integer id) { ParamCheckUtil.checkNotNull(id, "id"); return licenseService.detail(id); @@ -94,7 +92,7 @@ public class LicenseController { @OnlyAdmin @Post @Mapping("/update/enable-status") - public LicenseUpdateEnableStatusRes updateEnableStatus(@RequestBody LicenseUpdateEnableStatusReq req) { + public LicenseUpdateEnableStatusRes updateEnableStatus(LicenseUpdateEnableStatusReq req) { ParamCheckUtil.checkNotNull(req, "req"); ParamCheckUtil.checkNotNull(req.getId(), "id"); ParamCheckUtil.checkNotNull(req.getEnable(), "enable"); @@ -105,7 +103,7 @@ public class LicenseController { @OnlyAdmin @Post @Mapping("/delete") - public void delete(@RequestParam("id") Integer id) { + public void delete(Integer id) { ParamCheckUtil.checkNotNull(id, "id"); licenseService.delete(id); @@ -114,7 +112,7 @@ public class LicenseController { @OnlyAdmin @Post @Mapping("/reset") - public void reset(@RequestParam("id") Integer id) { + public void reset(Integer id) { ParamCheckUtil.checkNotNull(id, "id"); licenseService.reset(id); diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/LicenseMapper.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/LicenseMapper.java index 46baca89..9b9f5bdc 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/LicenseMapper.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/LicenseMapper.java @@ -98,7 +98,9 @@ public interface LicenseMapper extends BaseMapper { void delete(Integer id); @Select("select * from `license` where id = ?") - LicenseDO findById(Integer id); + default LicenseDO findById(Integer id) { + return this.selectById(id); + } @Update("update `license` set name = :name, update_time = :updateTime where id = :id") void update(@Param("id") Integer id, @Param("name") String name, @Param("updateTime") Date updateTime); @@ -111,7 +113,13 @@ public interface LicenseMapper extends BaseMapper { @ResultType(LicenseDO.class) @Select("select * from `license` where user_id = :userId and name =:name limit 0,1") - LicenseDO checkRepeat(@Param("userId") Integer userId, @Param("name") String name); + default LicenseDO checkRepeat(@Param("userId") Integer userId, @Param("name") String name) { + return this.selectOne(new LambdaQueryWrapper() + .eq(LicenseDO::getUserId, userId) + .eq(LicenseDO::getName, name) + .last("limit 1") + ); + } @ResultType(LicenseDO.class) @Select("select * from `license` where user_id = :userId and name =:name and id not in (:excludeIds) limit 0,1") diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortMappingMapper.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortMappingMapper.java index 3e510178..a6942d3a 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortMappingMapper.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortMappingMapper.java @@ -90,7 +90,11 @@ public interface PortMappingMapper extends BaseMapper { @ResultType(PortMappingDO.class) @Select("select * from port_mapping where license_id = ?") - List findListByLicenseId(Integer licenseId); + default List findListByLicenseId(Integer licenseId) { + return this.selectList(new LambdaQueryWrapper() + .eq(PortMappingDO::getLicenseId, licenseId) + ); + } @Update("update `port_mapping` set is_online = :isOnline,update_time = :updateTime where license_id = :licenseId and server_port = :serverPort") default void updateOnlineStatus(@Param("licenseId") Integer licenseId, @Param("serverPort") Integer serverPort, @Param("isOnline") Integer isOnline, @Param("updateTime") Date updateTime) { diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortPoolMapper.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortPoolMapper.java index 36842102..6d0c0f40 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortPoolMapper.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortPoolMapper.java @@ -21,6 +21,7 @@ */ package fun.asgc.neutrino.proxy.server.dal; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import fun.asgc.neutrino.core.annotation.Component; import fun.asgc.neutrino.core.annotation.Param; @@ -63,7 +64,11 @@ public interface PortPoolMapper extends BaseMapper { void delete(Integer id); @Select("select * from port_pool where port = ? limit 0,1") - PortPoolDO findByPort(Integer port); + default PortPoolDO findByPort(Integer port) { + return this.selectOne(new LambdaQueryWrapper() + .eq(PortPoolDO::getPort, port) + ); + } @Select("select * from port_pool where id = ?") PortPoolDO findById(Integer id); diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/entity/LicenseDO.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/entity/LicenseDO.java index 29a64d59..cd51aec8 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/entity/LicenseDO.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/entity/LicenseDO.java @@ -21,6 +21,7 @@ */ package fun.asgc.neutrino.proxy.server.dal.entity; +import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import fun.asgc.neutrino.core.db.annotation.Id; @@ -44,7 +45,7 @@ import java.util.Date; @TableName("license") public class LicenseDO { @Id - @TableId + @TableId(type = IdType.AUTO) private Integer id; /** * 名称 diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/LicenseService.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/LicenseService.java index b4916bcd..20f18e3a 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/LicenseService.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/LicenseService.java @@ -121,7 +121,7 @@ public class LicenseService implements Lifecycle { String key = UUID.randomUUID().toString().replaceAll("-", ""); Date now = new Date(); - licenseMapper.add(new LicenseDO() + licenseMapper.insert(new LicenseDO() .setName(req.getName()) .setKey(key) .setUserId(req.getUserId()) @@ -184,7 +184,7 @@ public class LicenseService implements Lifecycle { * @param id */ public void delete(Integer id) { - licenseMapper.delete(id); + licenseMapper.deleteById(id); // 更新VisitorChannel visitorChannelService.updateVisitorChannelByLicenseId(id, EnableStatusEnum.DISABLE.getStatus()); } diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/UserService.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/UserService.java index 53e9a624..f63246dd 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/UserService.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/UserService.java @@ -149,8 +149,11 @@ public class UserService { } public List list(UserListReq req) { - List list = userMapper.list(); - return list; + List userDOList = userMapper.selectList(new LambdaQueryWrapper() + .eq(UserDO::getEnable, EnableStatusEnum.ENABLE.getStatus()) + .orderByAsc(UserDO::getId) + ); + return mapperFactory.getMapperFacade().mapAsList(userDOList, UserListRes.class); } public UserInfoRes info(UserInfoReq req) { diff --git a/pom.xml b/pom.xml index ac1209cd..f88febbd 100644 --- a/pom.xml +++ b/pom.xml @@ -9,13 +9,6 @@ pom ${revision} - - org.noear - solon-parent - 2.2.1 - - - neutrino-core neutrino-proxy-core
+ * 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.proxy.server.base.db.template; + +import fun.asgc.neutrino.core.util.ArrayUtil; +import lombok.extern.slf4j.Slf4j; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * + * @author: aoshiguchen + * @date: 2022/6/27 + */ +@Slf4j +public abstract class PreparedStatementJdbcCallback implements JdbcCallback { + + @Override + public T execute() throws SQLException { + PreparedStatement pstm = null; + Object[] params = this.getParams(); + Connection conn = getConnection(); + + T res = null; + + log.debug("sql:" + this.getSql()); + StringBuffer sb = new StringBuffer(); + if (ArrayUtil.notEmpty(params)) { + for (Object o : params) { + sb.append(o).append(","); + } + + if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ',') { + sb.deleteCharAt(sb.length() - 1); + } + } + log.debug("params:" + sb.toString()); + pstm = conn.prepareStatement(this.getSql(), Statement.RETURN_GENERATED_KEYS); + if (ArrayUtil.notEmpty(params)) { + for (int i = 0; i < params.length; i++) { + pstm.setObject(i + 1, params[i]); + } + } + res = this.execute(pstm); + + return res; + } + + /** + * 获取参数 + * @return + */ + abstract Object[] getParams(); + + /** + * 获取sql语句 + * @return + */ + abstract String getSql(); + + /** + * 执行 + * @param ps + * @return + */ + abstract T execute(PreparedStatement ps) throws SQLException; + + /** + * 获取数据库连接 + * @return + */ + abstract Connection getConnection(); +} diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/SqlAndParams.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/SqlAndParams.java new file mode 100644 index 00000000..65d00f45 --- /dev/null +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/base/db/template/SqlAndParams.java @@ -0,0 +1,145 @@ +/** + * 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.proxy.server.base.db.template; + +import fun.asgc.neutrino.core.base.Orderly; +import fun.asgc.neutrino.core.util.ReflectUtil; + +import java.lang.reflect.Field; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * sql语句+sql参数的封装,用于支持以下3种用法 + * 1、jdbcTemplate.query(User.class,"select * from user where id = ?",1); + * 2、dbcTemplate.query(User.class,"select * from user where id = :id", new HashMap(){ + * { + * this.put("id","1"); + * } + * }); + * 3、dbcTemplate.query(User.class,"select * from user where id = :id", new User().setId("1")); + * @author: aoshiguchen + * @date: 2022/6/27 + */ +public class SqlAndParams { + private String sql; + private Object[] paramArray; + private Map paramMap; + private Object paramObject; + + public SqlAndParams(String sql, Object[] paramArray) { + this.sql = sql; + this.paramArray = paramArray; + } + + public SqlAndParams(String sql) { + this.sql = sql; + } + + public SqlAndParams(String sql,Map paramMap) { + this.sql = sql; + this.paramMap = paramMap; + this.initParams(); + } + + public SqlAndParams(String sql,Object paramObject) { + this.sql = sql; + this.paramObject = paramObject; + + this.initParamMap(); + this.initParams(); + } + + private void initParamMap(){ + if (null == paramObject) { + return; + } + if (null == paramMap) { + paramMap = new HashMap<>(); + } + for(Field field : ReflectUtil.getDeclaredFields(paramObject.getClass())){ + paramMap.put(field.getName(), ReflectUtil.getFieldValue(field, paramObject)); + } + } + + private void initParams() { + if (null == paramMap) { + paramMap = new HashMap<>(); + } + String originSql = sql; + List orderlyList = new ArrayList<>(); + for(String key : paramMap.keySet()){ + int index = originSql.indexOf(":" + key); + if(-1 != index){ + List currentList = new ArrayList<>(); + + // 解决数组、集合参数问题 + int count = 1; + Object tmp = paramMap.get(key); + if (null != tmp) { + if (tmp.getClass().isArray()) { + count = ((Object[])tmp).length; + currentList.addAll(Stream.of((Object[])tmp).map(e -> new Orderly(e, index)).collect(Collectors.toList())); + } else if (Collection.class.isAssignableFrom(tmp.getClass())) { + count = ((Collection)tmp).size(); + Object[] arr = ((Collection)tmp).toArray(); + paramMap.put(key, arr); + currentList.addAll((List)((Collection)tmp).stream().map(e -> new Orderly(e, index)).collect(Collectors.toList())); + } + } + List s = new ArrayList<>(); + for (int i = 0; i < count; i++) { + s.add("?"); + } + sql = sql.replaceFirst(":" + key, s.stream().collect(Collectors.joining(","))); + + if (currentList.isEmpty()) { + currentList.add(new Orderly(paramMap.get(key), index)); + } + + orderlyList.addAll(currentList); +// orderlyList.add(new Orderly(paramMap.get(key), index)); + } + } + + this.paramArray = orderlyList.stream().sorted().map(Orderly::getData).collect(Collectors.toList()).toArray(); + } + + public Object[] getParamArray(){ + return paramArray; + } + + public String getSql(){ + return sql; + } + + @Override + public String toString() { + return "SqlAndParams{" + + "sql='" + sql + '\'' + + ", paramArray=" + Arrays.toString(paramArray) + + ", paramMap=" + paramMap + + ", paramObject=" + paramObject + + '}'; + } +} diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/controller/LicenseController.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/controller/LicenseController.java index 08cf1df1..d1ce66c2 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/controller/LicenseController.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/controller/LicenseController.java @@ -21,8 +21,6 @@ */ package fun.asgc.neutrino.proxy.server.controller; -import fun.asgc.neutrino.core.web.annotation.RequestBody; -import fun.asgc.neutrino.core.web.annotation.RequestParam; import fun.asgc.neutrino.proxy.server.base.page.PageInfo; import fun.asgc.neutrino.proxy.server.base.page.PageQuery; import fun.asgc.neutrino.proxy.server.base.rest.annotation.OnlyAdmin; @@ -64,7 +62,7 @@ public class LicenseController { @OnlyAdmin @Post @Mapping("/create") - public LicenseCreateRes create(@RequestBody LicenseCreateReq req) { + public LicenseCreateRes create(LicenseCreateReq req) { ParamCheckUtil.checkNotNull(req, "req"); ParamCheckUtil.checkNotEmpty(req.getName(), "name"); ParamCheckUtil.checkNotNull(req.getUserId(), "userId"); @@ -75,7 +73,7 @@ public class LicenseController { @OnlyAdmin @Post @Mapping("/update") - public LicenseUpdateRes update(@RequestBody LicenseUpdateReq req) { + public LicenseUpdateRes update(LicenseUpdateReq req) { ParamCheckUtil.checkNotNull(req, "req"); ParamCheckUtil.checkNotNull(req.getId(), "id"); ParamCheckUtil.checkNotEmpty(req.getName(), "name"); @@ -85,7 +83,7 @@ public class LicenseController { @Post @Mapping("/detail") - public LicenseDetailRes detail(@RequestParam("id") Integer id) { + public LicenseDetailRes detail(Integer id) { ParamCheckUtil.checkNotNull(id, "id"); return licenseService.detail(id); @@ -94,7 +92,7 @@ public class LicenseController { @OnlyAdmin @Post @Mapping("/update/enable-status") - public LicenseUpdateEnableStatusRes updateEnableStatus(@RequestBody LicenseUpdateEnableStatusReq req) { + public LicenseUpdateEnableStatusRes updateEnableStatus(LicenseUpdateEnableStatusReq req) { ParamCheckUtil.checkNotNull(req, "req"); ParamCheckUtil.checkNotNull(req.getId(), "id"); ParamCheckUtil.checkNotNull(req.getEnable(), "enable"); @@ -105,7 +103,7 @@ public class LicenseController { @OnlyAdmin @Post @Mapping("/delete") - public void delete(@RequestParam("id") Integer id) { + public void delete(Integer id) { ParamCheckUtil.checkNotNull(id, "id"); licenseService.delete(id); @@ -114,7 +112,7 @@ public class LicenseController { @OnlyAdmin @Post @Mapping("/reset") - public void reset(@RequestParam("id") Integer id) { + public void reset(Integer id) { ParamCheckUtil.checkNotNull(id, "id"); licenseService.reset(id); diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/LicenseMapper.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/LicenseMapper.java index 46baca89..9b9f5bdc 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/LicenseMapper.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/LicenseMapper.java @@ -98,7 +98,9 @@ public interface LicenseMapper extends BaseMapper { void delete(Integer id); @Select("select * from `license` where id = ?") - LicenseDO findById(Integer id); + default LicenseDO findById(Integer id) { + return this.selectById(id); + } @Update("update `license` set name = :name, update_time = :updateTime where id = :id") void update(@Param("id") Integer id, @Param("name") String name, @Param("updateTime") Date updateTime); @@ -111,7 +113,13 @@ public interface LicenseMapper extends BaseMapper { @ResultType(LicenseDO.class) @Select("select * from `license` where user_id = :userId and name =:name limit 0,1") - LicenseDO checkRepeat(@Param("userId") Integer userId, @Param("name") String name); + default LicenseDO checkRepeat(@Param("userId") Integer userId, @Param("name") String name) { + return this.selectOne(new LambdaQueryWrapper() + .eq(LicenseDO::getUserId, userId) + .eq(LicenseDO::getName, name) + .last("limit 1") + ); + } @ResultType(LicenseDO.class) @Select("select * from `license` where user_id = :userId and name =:name and id not in (:excludeIds) limit 0,1") diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortMappingMapper.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortMappingMapper.java index 3e510178..a6942d3a 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortMappingMapper.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortMappingMapper.java @@ -90,7 +90,11 @@ public interface PortMappingMapper extends BaseMapper { @ResultType(PortMappingDO.class) @Select("select * from port_mapping where license_id = ?") - List findListByLicenseId(Integer licenseId); + default List findListByLicenseId(Integer licenseId) { + return this.selectList(new LambdaQueryWrapper() + .eq(PortMappingDO::getLicenseId, licenseId) + ); + } @Update("update `port_mapping` set is_online = :isOnline,update_time = :updateTime where license_id = :licenseId and server_port = :serverPort") default void updateOnlineStatus(@Param("licenseId") Integer licenseId, @Param("serverPort") Integer serverPort, @Param("isOnline") Integer isOnline, @Param("updateTime") Date updateTime) { diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortPoolMapper.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortPoolMapper.java index 36842102..6d0c0f40 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortPoolMapper.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/PortPoolMapper.java @@ -21,6 +21,7 @@ */ package fun.asgc.neutrino.proxy.server.dal; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import fun.asgc.neutrino.core.annotation.Component; import fun.asgc.neutrino.core.annotation.Param; @@ -63,7 +64,11 @@ public interface PortPoolMapper extends BaseMapper { void delete(Integer id); @Select("select * from port_pool where port = ? limit 0,1") - PortPoolDO findByPort(Integer port); + default PortPoolDO findByPort(Integer port) { + return this.selectOne(new LambdaQueryWrapper() + .eq(PortPoolDO::getPort, port) + ); + } @Select("select * from port_pool where id = ?") PortPoolDO findById(Integer id); diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/entity/LicenseDO.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/entity/LicenseDO.java index 29a64d59..cd51aec8 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/entity/LicenseDO.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/dal/entity/LicenseDO.java @@ -21,6 +21,7 @@ */ package fun.asgc.neutrino.proxy.server.dal.entity; +import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import fun.asgc.neutrino.core.db.annotation.Id; @@ -44,7 +45,7 @@ import java.util.Date; @TableName("license") public class LicenseDO { @Id - @TableId + @TableId(type = IdType.AUTO) private Integer id; /** * 名称 diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/LicenseService.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/LicenseService.java index b4916bcd..20f18e3a 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/LicenseService.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/LicenseService.java @@ -121,7 +121,7 @@ public class LicenseService implements Lifecycle { String key = UUID.randomUUID().toString().replaceAll("-", ""); Date now = new Date(); - licenseMapper.add(new LicenseDO() + licenseMapper.insert(new LicenseDO() .setName(req.getName()) .setKey(key) .setUserId(req.getUserId()) @@ -184,7 +184,7 @@ public class LicenseService implements Lifecycle { * @param id */ public void delete(Integer id) { - licenseMapper.delete(id); + licenseMapper.deleteById(id); // 更新VisitorChannel visitorChannelService.updateVisitorChannelByLicenseId(id, EnableStatusEnum.DISABLE.getStatus()); } diff --git a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/UserService.java b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/UserService.java index 53e9a624..f63246dd 100644 --- a/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/UserService.java +++ b/neutrino-proxy-server/src/main/java/fun/asgc/neutrino/proxy/server/service/UserService.java @@ -149,8 +149,11 @@ public class UserService { } public List list(UserListReq req) { - List list = userMapper.list(); - return list; + List userDOList = userMapper.selectList(new LambdaQueryWrapper() + .eq(UserDO::getEnable, EnableStatusEnum.ENABLE.getStatus()) + .orderByAsc(UserDO::getId) + ); + return mapperFactory.getMapperFacade().mapAsList(userDOList, UserListRes.class); } public UserInfoRes info(UserInfoReq req) { diff --git a/pom.xml b/pom.xml index ac1209cd..f88febbd 100644 --- a/pom.xml +++ b/pom.xml @@ -9,13 +9,6 @@ pom ${revision} - - org.noear - solon-parent - 2.2.1 - - - neutrino-core neutrino-proxy-core