都说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();
}
}
}