I am using Mybatis to make a CRUD application for a database and since all of my methods contain repetitive code when opening and closing an SQL session I would like to use an invocation handler to minimize the code repetition. Almost all of my methods look something like this:
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();
}
}
My question is how do I properly write and call the invocation handler, keeping in mind that the application remains thread-safe?
I solved the problem so I will answer my own question, the proper way to open and close an sql session using an invocation handler was to store the sqlSession in 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;
}
}
and change the above class to
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);
}
and call the function like this
DialogService ds = (DialogService) ConnectionHandler.newInstance(new DialogServiceImpl());
ds.removeDefDialog(defDialog);