使用临时兼容方案,解决jdbctemplate新增数据时,设置自增主键的问题

This commit is contained in:
aoshiguchen
2023-02-05 12:02:54 +08:00
parent 796cf7b18e
commit 37ee8021be
4 changed files with 214 additions and 63 deletions
@@ -21,15 +21,15 @@
*/
package fun.asgc.neutrino.core.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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
*
@@ -38,6 +38,8 @@ import java.util.Map;
*/
public class JdbcOperations {
private static final JdbcOperations instance = new JdbcOperations();
private static final Map<Class<?>, Field> generateIdFieldMap = new ConcurrentHashMap<>();
private JdbcOperations() {
@@ -85,6 +87,45 @@ public class JdbcOperations {
});
}
/**
* 执行更新操作
* 临时兼容返设主键问题
* @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
@@ -225,4 +266,28 @@ public class JdbcOperations {
});
}
/**
* 获取自动生成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;
}
}
@@ -21,16 +21,12 @@
*/
package fun.asgc.neutrino.core.db.template;
import fun.asgc.neutrino.core.util.ArrayUtil;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
*
@@ -74,6 +70,31 @@ public class JdbcTemplate {
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());
}
@@ -83,7 +104,8 @@ public class JdbcTemplate {
}
public int updateByModel(String sql, Object model) throws SQLException {
return update(new SqlAndParams(sql, model));
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 {
@@ -27,7 +27,6 @@ import fun.asgc.neutrino.core.annotation.Component;
import fun.asgc.neutrino.core.annotation.Match;
import fun.asgc.neutrino.core.annotation.NonIntercept;
import fun.asgc.neutrino.core.util.ChannelUtil;
import fun.asgc.neutrino.core.util.CollectionUtil;
import fun.asgc.neutrino.core.util.StringUtil;
import fun.asgc.neutrino.proxy.core.*;
import fun.asgc.neutrino.proxy.server.base.proxy.ProxyConfig;
@@ -38,27 +37,14 @@ import fun.asgc.neutrino.proxy.server.constant.SuccessCodeEnum;
import fun.asgc.neutrino.proxy.server.dal.LicenseMapper;
import fun.asgc.neutrino.proxy.server.dal.entity.ClientConnectRecordDO;
import fun.asgc.neutrino.proxy.server.dal.entity.LicenseDO;
import fun.asgc.neutrino.proxy.server.dal.entity.PortMappingDO;
import fun.asgc.neutrino.proxy.server.dal.entity.UserDO;
import fun.asgc.neutrino.proxy.server.proxy.core.BytesMetricsHandler;
import fun.asgc.neutrino.proxy.server.proxy.core.VisitorChannelHandler;
import fun.asgc.neutrino.proxy.server.proxy.domain.CmdChannelAttachInfo;
import fun.asgc.neutrino.proxy.server.proxy.domain.ProxyMapping;
import fun.asgc.neutrino.proxy.server.service.*;
import fun.asgc.neutrino.proxy.server.util.ProxyUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import java.net.BindException;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
*
@@ -70,10 +56,6 @@ import java.util.stream.Collectors;
@Match(type = Constants.ProxyDataTypeName.AUTH)
@Component
public class ProxyMessageAuthHandler implements ProxyMessageHandler {
@Autowired("serverBossGroup")
private NioEventLoopGroup serverBossGroup;
@Autowired("serverWorkerGroup")
private NioEventLoopGroup serverWorkerGroup;
@Autowired
private ProxyConfig proxyConfig;
@Autowired
@@ -90,6 +72,8 @@ public class ProxyMessageAuthHandler implements ProxyMessageHandler {
private ClientConnectRecordService clientConnectRecordService;
@Autowired
private LicenseMapper licenseMapper;
@Autowired
private VisitorChannelService visitorChannelService;
@Override
public void handle(ChannelHandlerContext ctx, ProxyMessage proxyMessage) {
@@ -173,46 +157,12 @@ public class ProxyMessageAuthHandler implements ProxyMessageHandler {
// 更新license在线状态
licenseMapper.updateOnlineStatus(licenseDO.getId(), OnlineStatusEnum.ONLINE.getStatus(), now);
List<PortMappingDO> portMappingList = portMappingService.findEnableListByLicenseId(licenseDO.getId());
// 没有端口映射仍然保持连接
ProxyUtil.initProxyInfo(licenseDO.getId(), ProxyMapping.buildList(portMappingList));
ProxyUtil.addCmdChannel(licenseDO.getId(), ctx.channel(), portMappingList.stream().map(PortMappingDO::getServerPort).collect(Collectors.toSet()));
startUserPortServer(ProxyUtil.getAttachInfo(ctx.channel()), portMappingList);
// 初始化VisitorChannel
visitorChannelService.initVisitorChannel(licenseDO.getId(), ctx.channel());
}
@Override
public String name() {
return ProxyDataTypeEnum.AUTH.getDesc();
}
private void startUserPortServer(CmdChannelAttachInfo cmdChannelAttachInfo, List<PortMappingDO> portMappingList) {
if (CollectionUtil.isEmpty(portMappingList)) {
return;
}
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(serverBossGroup, serverWorkerGroup)
.channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addFirst(new BytesMetricsHandler());
ch.pipeline().addLast(new VisitorChannelHandler());
}
});
for (PortMappingDO portMapping : portMappingList) {
try {
proxyMutualService.bindServerPort(cmdChannelAttachInfo, portMapping.getServerPort());
bootstrap.bind(portMapping.getServerPort()).get();
log.info("绑定用户端口: {}", portMapping.getServerPort());
} catch (Exception ex) {
// BindException表示该端口已经绑定过
if (!(ex.getCause() instanceof BindException)) {
throw new RuntimeException(ex);
}
}
}
}
}
@@ -0,0 +1,114 @@
/**
* 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.service;
import fun.asgc.neutrino.core.annotation.Autowired;
import fun.asgc.neutrino.core.annotation.Component;
import fun.asgc.neutrino.core.annotation.NonIntercept;
import fun.asgc.neutrino.core.util.CollectionUtil;
import fun.asgc.neutrino.proxy.server.dal.entity.PortMappingDO;
import fun.asgc.neutrino.proxy.server.proxy.core.BytesMetricsHandler;
import fun.asgc.neutrino.proxy.server.proxy.core.VisitorChannelHandler;
import fun.asgc.neutrino.proxy.server.proxy.domain.CmdChannelAttachInfo;
import fun.asgc.neutrino.proxy.server.proxy.domain.ProxyMapping;
import fun.asgc.neutrino.proxy.server.util.ProxyUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import java.net.BindException;
import java.util.List;
import java.util.stream.Collectors;
/**
* 访问者通道服务
* @author: aoshiguchen
* @date: 2023/2/5
*/
@Slf4j
@NonIntercept
@Component
public class VisitorChannelService {
@Autowired("serverBossGroup")
private NioEventLoopGroup serverBossGroup;
@Autowired("serverWorkerGroup")
private NioEventLoopGroup serverWorkerGroup;
@Autowired
private PortMappingService portMappingService;
@Autowired
private ProxyMutualService proxyMutualService;
/**
* 初始化
* @param licenseId
*/
public void initVisitorChannel(Integer licenseId, Channel cmdChannel) {
List<PortMappingDO> portMappingList = portMappingService.findEnableListByLicenseId(licenseId);
// 没有端口映射仍然保持连接
ProxyUtil.initProxyInfo(licenseId, ProxyMapping.buildList(portMappingList));
ProxyUtil.addCmdChannel(licenseId, cmdChannel, portMappingList.stream().map(PortMappingDO::getServerPort).collect(Collectors.toSet()));
startUserPortServer(ProxyUtil.getAttachInfo(cmdChannel), portMappingList);
}
/**
* 更新
* 触发时机:新增端口映射、修改端口映射、删除端口映射、禁用端口映射、启用端口映射、禁用license、启用license、禁用用户、启用用户
* @param licenseId
*/
public void UpdateVisitorChannel(Integer licenseId) {
}
private void startUserPortServer(CmdChannelAttachInfo cmdChannelAttachInfo, List<PortMappingDO> portMappingList) {
if (CollectionUtil.isEmpty(portMappingList)) {
return;
}
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(serverBossGroup, serverWorkerGroup)
.channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addFirst(new BytesMetricsHandler());
ch.pipeline().addLast(new VisitorChannelHandler());
}
});
for (PortMappingDO portMapping : portMappingList) {
try {
proxyMutualService.bindServerPort(cmdChannelAttachInfo, portMapping.getServerPort());
bootstrap.bind(portMapping.getServerPort()).get();
log.info("绑定用户端口: {}", portMapping.getServerPort());
} catch (Exception ex) {
// BindException表示该端口已经绑定过
if (!(ex.getCause() instanceof BindException)) {
throw new RuntimeException(ex);
}
}
}
}
}