1.前言
最近在做一个java的客户端程序,Swing是少不了,关键还要连数据库(Oracle)。面对这样一个程序,我们开始借组Spring的JDBC模块。大量的拼接Sql的确让我们很头疼(原谅我们这陈旧的技术吧),所以我们决定改成Mybatis。但是开发了一段时间,发现每次调用一个Mapper的方法都要进行各种的打开和关闭Session,对于我这个有代码洁癖的人怎么能忍受的了。想着引用Spring-Mybatis也没说明必要,毕竟那一阵套Spring框架,虽然轻,但是对于这个CS客户端程序貌似有点小题大做了。所以,我就决定编写一个程序。如下代码是一个简单的实例,功能能够实现,不过还是没有考虑到缓冲、事务相关的信息。不过这都是后期优化的事了。那就直接上代码吧。
2. 代码
package cn.surpass.proxy;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import static java.lang.reflect.Proxy.newProxyInstance;
/**
* cn.surpass.proxy
*
* @author surpass
* @date 2020/1/6
*/
public class MybatisProxy {
public static <T> T getMapper(SqlSessionFactory sqlSessionFactory, Class<T> t) {
if (!t.isInterface()) {
throw new IllegalArgumentException("t is not a Interface");
}
return (T) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
new Class[]{t}, new SqlSessionInterceptor<T>(sqlSessionFactory, t));
}
private static class SqlSessionInterceptor<T> implements InvocationHandler {
private Class<T> t;
private SqlSessionFactory sqlSessionFactory;
private SqlSessionInterceptor(SqlSessionFactory sqlSessionFactory, Class<T> t) {
this.sqlSessionFactory = sqlSessionFactory;
this.t = t;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
SqlSession sqlSession = sqlSessionFactory.openSession();
T mapperT = sqlSession.getMapper(t);
try {
Object result = method.invoke(mapperT, args);
sqlSession.commit(true);
return result;
} catch (Exception e) {
sqlSession.rollback();
throw e;
} finally {
if (sqlSession != null) {
sqlSession.close();
}
System.out.println("Session 已经关闭");
}
}
}
}