为了支持数据初始化逻辑,将JdbcTemplate代码迁移至server端。mybatis、hutool-db不方便直接sql操作

This commit is contained in:
aoshiguchen
2023-03-11 18:22:07 +08:00
parent 28625f193c
commit 6823ac07c4
21 changed files with 1626 additions and 71 deletions
+6 -1
View File
@@ -18,6 +18,7 @@
<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-api</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.noear</groupId>
@@ -42,7 +43,11 @@
<scope>system</scope>
<systemPath>${project.basedir}/../_solon_plugin/orika-solon-plugin/pom.xml</systemPath>
</dependency>
<!-- <dependency>-->
<!-- <groupId>cn.hutool</groupId>-->
<!-- <artifactId>hutool-db</artifactId>-->
<!-- <version>5.8.15</version>-->
<!-- </dependency>-->
<dependency>
<groupId>fun.asgc.neutrino</groupId>
<artifactId>neutrino-proxy-core</artifactId>
@@ -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<AppLoadEndEvent> {
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<AppLoadEndEvent> {
initDBData();
}
@Override
public void onEvent(AppLoadEndEvent appLoadEndEvent) throws Throwable {
// TODO 该事件有50%的概率不触发
}
/**
* 初始化数据库结构
*/
@@ -92,6 +101,7 @@ public class DBInitialize implements EventListener<AppLoadEndEvent> {
}
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<AppLoadEndEvent> {
}
}
}
// /**
// * 获取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
// );
// }
}
@@ -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;
@@ -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;
@@ -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<Boolean> 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;
}
}
@@ -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<String, String> 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<Class<?>, Cache<Field, String>> fieldToColumnCache = new MemoryCache<>();
private static final Object fieldToColumnCacheLock = new Object();
private static final Cache<Class<?>,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<Field> getField(Class<?> clazz, String column) {
try {
return LockUtil.doubleCheckProcess(
() -> !fieldToColumnCache.containsKey(clazz),
fieldToColumnCacheLock,
() -> initFieldCache(clazz),
() -> {
List<Field> list = Lists.newArrayList();
Cache<Field, String> 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<Field> getFieldList(Class<?> clazz) {
try {
return LockUtil.doubleCheckProcess(
() -> !fieldToColumnCache.containsKey(clazz),
fieldToColumnCacheLock,
() -> initFieldCache(clazz),
() -> {
List<Field> list = Lists.newArrayList();
Cache<Field, String> 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<Field, String> 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<Field> fieldSet = ReflectUtil.getDeclaredFields(clazz);
if (CollectionUtil.isEmpty(fieldSet)) {
return;
}
Cache<Field, String> 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);
}
}
@@ -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<String, String> {
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();
}
}
@@ -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<String, String> {
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();
}
}
@@ -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<T> {
/**
* 执行
* @return
*/
T execute() throws SQLException;
}
@@ -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<Class<?>, Field> generateIdFieldMap = new ConcurrentHashMap<>();
private JdbcOperations() {
}
public static JdbcOperations getInstance() {
return instance;
}
/**
* 通用执行方法
* @param callback
* @param <T>
* @return
*/
public <T> T execute(JdbcCallback<T> 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<Integer>(){
@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<Integer>(){
@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 <T>
* @return
*/
public <T> T executeQuery(final Connection conn,final Class<T> clazz,final String sql,final Object[] params) throws SQLException {
return this.execute(new PreparedStatementJdbcCallback<T>() {
@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<String,Object> map = new HashMap<String,Object>();
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<Field> 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 <T>
* @return
*/
public <T> List<T> executeQueryForList(final Connection conn, final Class<T> clazz, final String sql, final Object[] params) throws SQLException {
return this.execute(new PreparedStatementJdbcCallback<List<T>>() {
@Override
public List<T> execute(PreparedStatement ps) {
List<T> res = new ArrayList<T>();
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<String,Object> map = new HashMap<String,Object>();
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<Field> 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<Field> 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;
}
}
@@ -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<String,Object> 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> T query(Class<T> 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> T query(Class<T> clazz, SqlAndParams sqlAndParams) throws SQLException {
return query(clazz, sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public <T> T queryByMap(Class<T> clazz, String sql, Map<String,Object> params) throws SQLException {
return query(clazz, new SqlAndParams(sql, params));
}
public <T> T queryByModel(Class<T> clazz, String sql, Object model) throws SQLException {
return query(clazz, new SqlAndParams(sql, model));
}
public byte queryForByteByMap(String sql, Map<String,Object> 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<String,Object> 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<String,Object> 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<String,Object> 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<String,Object> 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<String,Object> 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<String,Object> 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<String,Object> 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<String,Object> 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<String,Object> queryForMapByMap(String sql, Map<String,Object> params) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, params);
return queryForMap(sql, sqlAndParams.getParamArray());
}
public Map<String,Object> queryForMapByModel(String sql, Object model) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, model);
return queryForMap(sql, sqlAndParams.getParamArray());
}
public Map<String,Object> queryForMap(String sql, Object ...params) throws SQLException {
return (Map<String,Object>)query(HashMap.class, sql, params);
}
public <T> List<T> queryForList(Class<T> clazz, String sql, Object ...params) throws SQLException {
List<T> 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 <T> List<T> queryForList(Class<T> clazz, SqlAndParams sqlAndParams) throws SQLException {
return queryForList(clazz, sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public <T> List<T> queryForListByMap(Class<T> clazz, String sql, Map<String,Object> params) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, params);
return queryForList(clazz, sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public <T> List<T> queryForListByModel(Class<T> clazz, String sql, Object model) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, model);
return queryForList(clazz, sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Byte> queryForListByteByMap(String sql, Map<String,Object> params) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, params);
return queryForListByte(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Byte> queryForListByteByModel(String sql, Object model) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, model);
return queryForListByte(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Byte> queryForListByte(String sql,Object ...params) throws SQLException {
return queryForList(byte.class, sql,params);
}
public List<Short> queryForListShortByMap(String sql, Map<String, Object> params) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, params);
return queryForListShort(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Short> queryForListShortByModel(String sql, Object model) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, model);
return queryForListShort(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Short> queryForListShort(String sql, Object ...params) throws SQLException {
return queryForList(short.class, sql, params);
}
public List<Integer> queryForListIntByMap(String sql, Map<String,Object> params) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, params);
return queryForListInt(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Integer> queryForListIntByModel(String sql, Object model) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, model);
return queryForListInt(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Integer> queryForListInt(String sql, Object ...params) throws SQLException {
return queryForList(int.class, sql, params);
}
public List<Long> queryForListLongByMap(String sql, Map<String,Object> params) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, params);
return queryForListLong(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Long> queryForListLongByModel(String sql, Object model) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, model);
return queryForListLong(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Long> queryForListLong(String sql,Object ...params) throws SQLException {
return queryForList(long.class, sql, params);
}
public List<Float> queryForListFloatByMap(String sql, Map<String,Object> params) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, params);
return queryForListFloat(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Float> queryForListFloatByModel(String sql, Object model) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, model);
return queryForListFloat(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Float> queryForListFloat(String sql, Object ...params) throws SQLException {
return queryForList(float.class, sql, params);
}
public List<Double> queryForListDoubleByMap(String sql ,Map<String,Object> params) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, params);
return queryForListDouble(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Double> queryForListDoubleByModel(String sql, Object model) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, model);
return queryForListDouble(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Double> queryForListDouble(String sql, Object ...params) throws SQLException {
return queryForList(double.class, sql, params);
}
public List<Character> queryForListCharByMap(String sql, Map<String,Object> params) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, params);
return queryForListChar(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Character> queryForListCharByModel(String sql, Object model) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, model);
return queryForListChar(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Character> queryForListChar(String sql, Object ...params) throws SQLException {
return queryForList(char.class, sql, params);
}
public List<Boolean> queryForListBooleanByMap(String sql, Map<String,Object> params) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, params);
return queryForListBoolean(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Boolean> queryForListBooleanByModel(String sql, Object model) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, model);
return queryForListBoolean(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Boolean> queryForListBoolean(String sql, Object ...params) throws SQLException {
return queryForList(boolean.class, sql, params);
}
public List<String> queryForListStringByMap(String sql, Map<String,Object> params) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, params);
return queryForListString(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<String> queryForListStringByModel(String sql, Object model) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, model);
return queryForListString(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<String> queryForListString(String sql, Object ...params) throws SQLException {
return queryForList(String.class, sql, params);
}
public List<Map> queryForListMap(String sql, Object ...params) throws SQLException {
return queryForList(Map.class, sql, params);
}
public List<Map> queryForListMapByMap(String sql, Map<String,Object> params) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, params);
return queryForListMap(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
public List<Map> queryForListMapByModel(String sql, Object model) throws SQLException {
SqlAndParams sqlAndParams = new SqlAndParams(sql, model);
return queryForListMap(sqlAndParams.getSql(), sqlAndParams.getParamArray());
}
}
@@ -0,0 +1,95 @@
/**
* Copyright (c) 2022 aoshiguchen
* <p>
* 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:
* <p>
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* <p>
* 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<T> implements JdbcCallback<T> {
@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();
}
@@ -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<String,Object>(){
* {
* 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<String,Object> 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<String,Object> 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<Orderly> orderlyList = new ArrayList<>();
for(String key : paramMap.keySet()){
int index = originSql.indexOf(":" + key);
if(-1 != index){
List<Orderly> 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<String> 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 +
'}';
}
}
@@ -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);
@@ -98,7 +98,9 @@ public interface LicenseMapper extends BaseMapper<LicenseDO> {
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<LicenseDO> {
@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<LicenseDO>()
.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")
@@ -90,7 +90,11 @@ public interface PortMappingMapper extends BaseMapper<PortMappingDO> {
@ResultType(PortMappingDO.class)
@Select("select * from port_mapping where license_id = ?")
List<PortMappingDO> findListByLicenseId(Integer licenseId);
default List<PortMappingDO> findListByLicenseId(Integer licenseId) {
return this.selectList(new LambdaQueryWrapper<PortMappingDO>()
.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) {
@@ -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<PortPoolDO> {
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<PortPoolDO>()
.eq(PortPoolDO::getPort, port)
);
}
@Select("select * from port_pool where id = ?")
PortPoolDO findById(Integer id);
@@ -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;
/**
* 名称
@@ -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());
}
@@ -149,8 +149,11 @@ public class UserService {
}
public List<UserListRes> list(UserListReq req) {
List<UserListRes> list = userMapper.list();
return list;
List<UserDO> userDOList = userMapper.selectList(new LambdaQueryWrapper<UserDO>()
.eq(UserDO::getEnable, EnableStatusEnum.ENABLE.getStatus())
.orderByAsc(UserDO::getId)
);
return mapperFactory.getMapperFacade().mapAsList(userDOList, UserListRes.class);
}
public UserInfoRes info(UserInfoReq req) {
-7
View File
@@ -9,13 +9,6 @@
<packaging>pom</packaging>
<version>${revision}</version>
<parent>
<groupId>org.noear</groupId>
<artifactId>solon-parent</artifactId>
<version>2.2.1</version>
<relativePath />
</parent>
<modules>
<module>neutrino-core</module>
<module>neutrino-proxy-core</module>