Hibernate事务回滚是否有效?

时间:2016-03-03 07:46:47

标签: java spring hibernate rollback

我有2个模型类:ModelA& ModelB

2个持久类:ModelADAO& ModelBDAO。在它的每个实现中,我确实使用事务回滚来保存(模型)方法。基本如下:

public class ModelADAOImpl implements ModelADAO {

    public bool save(modelA) {

        try {
            session = this.sessionFactory.openSession();
            transaction = session.beginTransaction();
            ...

            session.persist(modelA);

            ...
            transaction.commit();

        } catch(Exception e) {
            transaction.rollback();

        } finally {
            session.close();
        }
    }

}

public class ModelBDAOImpl implements ModelBDAO {

    public bool save(modelB) {

        try {
            session = this.sessionFactory.openSession();
            transaction = session.beginTransaction();
            ...

            session.persist(modelB);

            ...
            transaction.commit();

        } catch(Exception e) {
            transaction.rollback();

        } finally {
            session.close();
        }
    }

}

现在,我有其他类使用 saveAll(modelA,modelB) 方法来保存 modelA modelB <的信息/ strong>通过调用 modelADAO.save(modelA) modelBDAO.save(modelB)

public class WrapperDAOImpl implements WrapperDAO {

    @Autowired
    private ModelADAO modelADAO;

    @Autowired
    private ModelBDAO modelBDAO;

    public bool saveAll(modelA, modelB) {

        try {
            ...

            modelADAO.save(modelA);
            modelBDAO.save(modelB);

            ...

        } catch(Exception e) {
            ...

        } finally {
            ...
        }
    }

}

在这种情况下,如何为saveAll(modelA,modelB)应用回滚?因为我在每个save()方法中都打开并关闭了会话。

谢谢!

3 个答案:

答案 0 :(得分:1)

我建议你改变构建DAO的方式。我从不在DAO内部进行交易管理,而是在服务层管理交易。

通常,服务方法需要调用几个DAO的方法,因此您希望为所有人应用单个事务,正如您在问题中所述。

因此,我将事务管理转移到saveAll方法。显然,如果DAO保存方法在不管理事务的情况下调用,则此更改可能会导致错误。这就是我告诉你使用服务层的原因。

将事务管理留在DAO中的另一个选择可能是使用PROPAGATION=required的事务传播。但是我从未使用它并且不确定它是如何工作的,但至少在理论上它应该是这样的,如果在调用save方法时没有创建事务,它将被创建,但是如果有一个已经创建的交易,它将使用它。回滚将撤消所有更改。

答案 1 :(得分:0)

大多数框架适用的典型解决方案是按线程跟踪正在运行的事务,因此您将保持与正在运行的事务的线程本地。另一个解决方案是将tx作为参数传递给你的方法。

答案 2 :(得分:0)

您必须使用通用接口来保存您的数据,而不是依赖于entityA或entityB。而且对于您的模型,您必须拥有一个包含id的Base bean。

public class BaseBean{

 private Long id ;
//get + set

}

public class Aa extends BaseBean{

}

public class Bb extends BaseBean{

}

public interface daoRepository{
<T extends BaseBean> void save(Iterable<? extends T> objects);
}


public class daoImpl implements daoRepository{

    @Override
    public <T extends BaseBean> void save(Iterable<? extends T> objects){
      try {
        session = this.sessionFactory.openSession();
        transaction = session.beginTransaction();
        ...
        for (T t : objects) {
        session.persist(t);
        }
        ...
        transaction.commit();

    } catch(Exception e) {
        transaction.rollback();

    } finally {
        session.close();
    }
    }
}