使用调用处理程序打开和关闭 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);