繁体   English   中英

在单个事务中刷新和持久性违反多个约束

[英]Multiple constraint violation on flush and persist in a single transaction

我正在尝试使用 JPA (EclipseLink) 在一个事务中保留许多记录。 该条目具有在 DB 上定义的主键。

我的提要中有一些重复项,所以我知道会违反约束。 我想捕获单个项目的约束违规异常并继续保留其他项目。

这是我的代码:

实体:

@Entity
@Table(name="TEST")
public class TestEntity {

    @Id
    private String name;

    public TestEntity() {

    }

    public TestEntity(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

手术:

@Transactional
public void test() {

    List<String> list = Arrays.asList("A", "B","C","D","D","E","F","G");//duplicated D

    for(String name: list) {
        try {
            TestEntity entity = new TestEntity(name);
            logger.info("" + entity);
            entityManager.persist(entity);
            logger.info("Persist done");
            entityManager.flush();
            logger.info("Flush done");
        } catch(RuntimeException e) {
            logger.warn("Entry {}  was skipped due to following exception {}.",  name, e.getLocalizedMessage());
        }
    }

    logger.info("Importing dictionary finished. ");
}

结果,我得到了第二个 D 的约束违规异常(这是我所期望的),但我也得到了下一个项目的这个异常,这是我不明白的事情。

我得到:内部异常:java.sql.SQLIntegrityConstraintViolationException:ORA-00001:唯一约束(BBHDEV4.SYS_C0023890)违反

是什么导致了这个问题?

问题是第二个D仍然是同一个 Transaction / Unit of Work 的一部分,所以在接下来的迭代中,hibernate 尝试再次保存它。

要解决此问题(使用 vanilla JPA),您可以

使用休眠,您有第三个选项,即使用无状态会话,但我不知道eclipselink是否具有无状态实体管理器的概念

您的实体管理器维护一个由所有托管实体(即持久性上下文)及其对象的事务状态组成的状态。

因此,在触发违反约束的刷新之后,D 实体仍处于管理状态并处于陈旧状态,并将在下一次显式刷新调用(您不应显式调用刷新)或当前事务结束时再次刷新。 在恢复循环之前,您必须手动从持久性上下文 ( detach() ) 中逐出 D 实体。

无论如何,如果您的所有操作都是同一个事务的一部分,并且在事务边界之外抛出错误,事务管理器将自动回滚整个事务。

一个事务是一个工作单元,如果你不想你的不同操作是独立的,你必须在不同的事务中执行它们。 通常实体管理器的作用域与事务相同(至少当由容器管理时,即注入@PersitenceContext),您将同时解决这两个问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM