都说spring利用AOP实现自动事务处理机制非常好,但在只有hibernate这个框架情况下,我们开启session、管理事务就往往很麻烦。
public void save(Object obj){ Session session = this.getSession(); Transaction tran = session.beginTransaction(); try { session.save(obj); tran.commit(); } catch (Exception e) { //事务回滚 if(tran.isActive()){ tran.rollback(); } }finally{ //关闭session if(session!=null){ session.close(); } } }
最近也刚学会动态代理和反射,我就在想,是否可以用代理+反射实现session自动创建销毁,事务自动提交。
BaseDaoImpl需要有两个公共变量session和transaction,每个方法体里只需要写CRUD代码即可:
public class BaseDaoImpl implements BaseDao { public Session session = null; public Transaction tran = null; @Override public void delete(Class clazz, Serializable id) throws Exception { // TODO Auto-generated method stub Object obj = session.load(clazz, id); session.delete(obj); } }
最后看最重要的部分,实现session和transaction的动态代理类:
package com.bless.hibernatedemo.util; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import org.hibernate.Session; import org.hibernate.Transaction; public class DaoProxy implements InvocationHandler { private Object obj; // 绑定关系,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时,执行invoke方法。 // Proxy.newProxyInstance的第三个参数是表明这些被拦截的方法执行时需要执行哪个InvocationHandler的invoke方法 public Object bindRelation(Object obj) { this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj .getClass().getInterfaces(), this); } // 拦截关联的这个实现类的方法被调用时将被执行 @Override public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable { Class clazz = obj.getClass(); // 反射获取session和tran两个属性对象 Field fSession = clazz.getField("session"); Field fTran = clazz.getField("tran"); Session session = HibernateUtils.currentSession(); // 给Dao中的session赋值 fSession.set(obj, session); // 然后通过session打开事务 Transaction tran = session.beginTransaction(); // 再将事务对象set到对象中 fTran.set(obj, tran); try { // 哇咔咔,执行dao方法 Object result = arg1.invoke(obj, arg2); // 当然事务是要提交滴 tran.commit(); return result; } catch (Exception e) { // 发生异常,事务回滚 if (tran.isActive()) { tran.rollback(); } throw e; } finally { // session关闭操作 if (session != null) { HibernateUtils.colseSession(); } } } }
最后测试一下:
public class HibernateTest extends TestCase { public void testSave(){ BaseDaoImpl baseDaoImpl = new BaseDaoImpl(); DaoProxy proxy = new DaoProxy(); BaseDao baseDao = (BaseDao) proxy.bindRelation(baseDaoImpl); try { //删除User表中id为1的字段 baseDao.delete(User.class,1); } catch (Exception e) { e.printStackTrace(); } } }