首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在JPA中回滚一系列持久化语句?

如何在JPA中回滚一系列持久化语句?
EN

Stack Overflow用户
提问于 2015-12-18 21:15:31
回答 2查看 8.2K关注 0票数 5

在这种情况下,我需要回滚一系列持久化方法.我在我的控制器类中有一个方法,我从那里调用持久化方法。

控制器类:

代码语言:javascript
运行
AI代码解释
复制
@EJB
private jpa.session.ClassMasterFacade ejbFacadeCM;
@EJB
private jpa.session.StudentMasterFacade ejbFacadeSM;
@EJB
private jpa.session.ParentsMasterFacade ejbFacadePM;
@EJB
private jpa.session.AddressMasterFacade ejbFacadeAM;

public String confirmData() {
    try {
        ejbFacadeSM;.create(selectedSM);
        ejbFacadeCM;.create(selectedCM)
        ejbFacadeAM;.create(selectedAM);
        ejbFacadePM;.create(selectedPM);
    } catch (Exception e) {
        //rollback all
        JsfUtil.addErrorMessage(e, ResourceBundle.getBundle ("/resources/Bundle").getString("PersistenceErrorOccured"));
        return null;
    }
 }

示例Facade类:

代码语言:javascript
运行
AI代码解释
复制
@Stateless
public class ClassMasterFacade extends AbstractFacade<ClassMaster> {

    @PersistenceContext(unitName = "sdjv_smsPU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public ClassMasterFacade() {
        super(ClassMaster.class);
    }

}

所有其他facade类都类似于上面的类。摘要类是:

代码语言:javascript
运行
AI代码解释
复制
public abstract class AbstractFacade<T> {
    private Class<T> entityClass;

    public AbstractFacade(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    protected abstract EntityManager getEntityManager();

    public void create(T entity) {
        getEntityManager().persist(entity);
    }

    public void edit(T entity) {
        getEntityManager().merge(entity);
    }

    public void remove(T entity) {
        getEntityManager().remove(getEntityManager().merge(entity));
    }

    public T find(Object id) {
        return getEntityManager().find(entityClass, id);
    }
}

如果发现任何异常,我希望回滚所有create方法。

我搜索并找到一些答案:

我对JPA很陌生,刚刚开始探索。我是不是漏掉了什么概念?

直到有一个问题,不知道它是否相关。在所有实体类中,我都有一个更新后的自动生成键。问题是,如果异常发生在第二个create语句中,则会生成第一个create语句的自动生成键,但在mysql中仍然不会以excepted..But的形式更新所有语句,如果成功的话,键序列就会中断。

实体类:

代码语言:javascript
运行
AI代码解释
复制
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "class_group_id")
private Integer classGroupId;
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-18 22:35:30

使用javax.transaction.UserTransaction,它在任何标准Java环境中都是可用的。

使用非常简单,注入它并使用以下方法:

  • 启动事务的begin()
  • 如果所有操作都成功,并且要提交结果,则为commit()
  • 如果发生错误并希望回滚到调用rollback()时的时间点,则为begin()

请参阅:关于UserTransaction的Oracle文档

代码语言:javascript
运行
AI代码解释
复制
@Resource
UserTransaction tran;

...

public void confirmData (){

    tran.begin();
    try {
        ejbFacadeSM.create(selectedSM);
        ejbFacadeCM.create(selectedCM)
        ejbFacadeAM.create(selectedAM);
        ejbFacadePM.create(selectedPM);

        // Create's succeeded, commit transaction.
        tran.commit();
    } catch (Exception e) {
        // Error occurred, rollback transaction
        tran.rollback();
    }
}
票数 5
EN

Stack Overflow用户

发布于 2015-12-31 05:10:11

回滚可以由事务自动完成。只需告诉您的方法,它必须在事务中运行,如果不存在,将创建一个新事务。您可以通过使用事务属性REQUIRES_NEW注释您的方法来做到这一点。

代码语言:javascript
运行
AI代码解释
复制
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public String confirmData() {
    try{
        ejbFacadeSM.create(selectedSM);
        ejbFacadeCM.create(selectedCM)
        ejbFacadeAM.create(selectedAM);
        ejbFacadePM.create(selectedPM);
    }catch(PersistenceException e){
        //do some stuff
    }
}

如果您的一个语句在PersistenceException中失败,则在事务结束时将回滚所有操作。事务以您的方法结束。

请注意这方面的一个例外,正如规范(在JSR 338中)所述:

PersistenceException的所有实例(除了NoResultExceptionNonUniqueResultExceptionLockTimeoutExceptionQueryTimeoutException实例之外)都将导致当前事务(如果一个事务是活动的,并且持久性上下文已被连接到它)标记为回滚。

示例:如果您的第4条语句ejbFacadePM.create(selectedPM)LockTimeoutException中失败,则只有第4条语句被回滚,但是您的事务不会被标记为回滚。接下来,您将到达代码的catch块。这为您提供了从异常中恢复的机会,可能会编写一些代码再次尝试第四条语句。当您离开您的confirmData()方法时,事务仍然将被提交到DB中,其中包含您在以前的ejbFacadeXX方法中所做的更改。

如果您仍然说必须回滚整个事务,包括所有发出的语句,无论发生何种异常,仍然可以告诉事务回滚到catch块中。因此,要么使用rollback()用于Bean管理事务 (BMT),要么使用setRollbackOnly()用于容器管理事务(ContainerManagedTransaction,CMT)。如果您没有将您的事务设置为bean管理(例如,通过使用@TransactionManagement( TransactionManagementType.BEAN )),那么您的事务很可能是容器管理的,这是自JEE 5以来的默认设置。

不推荐BMT,因为它要求您的应用程序完成服务器已经可以为您完成的工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34367517

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档