使用调用处理程序打开和关闭 SQL 会话
Using invocation handler to open and close SQL session
我正在使用 Mybatis 为数据库创建一个 CRUD 应用程序,因为我的所有方法在打开和关闭 SQL 会话时都包含重复代码,所以我想使用调用处理程序来最大程度地减少代码重复.几乎我所有的方法都是这样的:
public int deleteDefDialog(DefDialog defDialog) {
SqlSession sqlSession = ConnectionFactory.getSqlSessionFactory()
.openSession();
try {
DialogMapper dialogMapper = sqlSession
.getMapper(DialogMapper.class);
int i = dialogMapper.deleteDefDialog(defDialog);
sqlSession.commit();
return i;
} finally {
sqlSession.close();
}
}
public DefDialog selectDefDialog(BigDecimal i) {
SqlSession sqlSession = ConnectionFactory.getSqlSessionFactory()
.openSession();
try {
DialogMapper dialogMapper = sqlSession
.getMapper(DialogMapper.class);
return dialogMapper.selectDefDialog(i);
} finally {
sqlSession.close();
}
}
我的问题是如何正确编写和调用调用处理程序,同时牢记应用程序保持线程安全?
我解决了这个问题,所以我会回答我自己的问题,使用调用处理程序打开和关闭 sql 会话的正确方法是将 sqlSession 存储在 ThreadLocal 中。
ConnectionHandler.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.apache.ibatis.session.SqlSession;
public class ConnectionHandler implements InvocationHandler {
private Object obj;
private static final ThreadLocal<SqlSession> session = new ThreadLocal<SqlSession>();
public static SqlSession getSession(){
return session.get();
}
public static Object newInstance(Object obj) {
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new ConnectionHandler(obj));
}
private ConnectionHandler(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Object result = null;
SqlSession sqlSession = ConnectionFactory.getSqlSessionFactory()
.openSession();
session.set(sqlSession);
try {
result = m.invoke(obj, args);
sqlSession.commit();
} catch (Exception e) {
sqlSession.rollback();
throw e;
} finally {
sqlSession.close();
}
return result;
}
}
并将上面的class改为
DialogServiceImpl.java
public int deleteDefDialog(DefDialog defDialog) {
DialogMapper dialogMapper = ConnectionHandler.getSession()
.getMapper(DialogMapper.class);
int i = dialogMapper.deleteDefDialog(defDialog);
return i;
}
public DefDialog selectDefDialog(BigDecimal i) {
DialogMapper dialogMapper = ConnectionHandler.getSession()
.getMapper(DialogMapper.class);
return dialogMapper.selectDefDialog(i);
}
并像这样调用函数
DialogService ds = (DialogService) ConnectionHandler.newInstance(new DialogServiceImpl());
ds.removeDefDialog(defDialog);
我正在使用 Mybatis 为数据库创建一个 CRUD 应用程序,因为我的所有方法在打开和关闭 SQL 会话时都包含重复代码,所以我想使用调用处理程序来最大程度地减少代码重复.几乎我所有的方法都是这样的:
public int deleteDefDialog(DefDialog defDialog) {
SqlSession sqlSession = ConnectionFactory.getSqlSessionFactory()
.openSession();
try {
DialogMapper dialogMapper = sqlSession
.getMapper(DialogMapper.class);
int i = dialogMapper.deleteDefDialog(defDialog);
sqlSession.commit();
return i;
} finally {
sqlSession.close();
}
}
public DefDialog selectDefDialog(BigDecimal i) {
SqlSession sqlSession = ConnectionFactory.getSqlSessionFactory()
.openSession();
try {
DialogMapper dialogMapper = sqlSession
.getMapper(DialogMapper.class);
return dialogMapper.selectDefDialog(i);
} finally {
sqlSession.close();
}
}
我的问题是如何正确编写和调用调用处理程序,同时牢记应用程序保持线程安全?
我解决了这个问题,所以我会回答我自己的问题,使用调用处理程序打开和关闭 sql 会话的正确方法是将 sqlSession 存储在 ThreadLocal 中。
ConnectionHandler.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.apache.ibatis.session.SqlSession;
public class ConnectionHandler implements InvocationHandler {
private Object obj;
private static final ThreadLocal<SqlSession> session = new ThreadLocal<SqlSession>();
public static SqlSession getSession(){
return session.get();
}
public static Object newInstance(Object obj) {
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), new ConnectionHandler(obj));
}
private ConnectionHandler(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Object result = null;
SqlSession sqlSession = ConnectionFactory.getSqlSessionFactory()
.openSession();
session.set(sqlSession);
try {
result = m.invoke(obj, args);
sqlSession.commit();
} catch (Exception e) {
sqlSession.rollback();
throw e;
} finally {
sqlSession.close();
}
return result;
}
}
并将上面的class改为
DialogServiceImpl.java
public int deleteDefDialog(DefDialog defDialog) {
DialogMapper dialogMapper = ConnectionHandler.getSession()
.getMapper(DialogMapper.class);
int i = dialogMapper.deleteDefDialog(defDialog);
return i;
}
public DefDialog selectDefDialog(BigDecimal i) {
DialogMapper dialogMapper = ConnectionHandler.getSession()
.getMapper(DialogMapper.class);
return dialogMapper.selectDefDialog(i);
}
并像这样调用函数
DialogService ds = (DialogService) ConnectionHandler.newInstance(new DialogServiceImpl());
ds.removeDefDialog(defDialog);