如何隔离实体验证以防止整个批量(持久)事务的事务回滚?

时间:2014-05-14 04:30:20

标签: java jpa eclipselink java-ee-7

我有带验证注释的实体,例如@NotNull。我不知道如何在批量持久化操作中阻止容器管理的事务在ConstraintViolationException的情况下回滚,例如:

public void persistAll(List<TheEntity> entities) throws Exception{

for(TheEntity ent : entities){

em.persist(ent);

}

}

在try-catch中包装persist操作无法解决问题,因为即使捕获Constraint异常,该事务也会被标记为回滚(其他任何&#34;已验证的&#34;实体都不会被保留) 。我可以将每个实体的事务隔离开来,但我认为这会对性能产生很大影响(不确定这一点,我使用eclipselink进行批处理JDBC优化)。

我知道ContraintValidationException的行为正如JPA规范要求的那样(标记回滚),但我不确定我是否理解eclipselink批量优化的工作原理(批量操作是否需要)在一次交易中?)。

感谢您的关注。

问候。

编辑:Welp,eclipelink docs声明&#34;批处理写入可以通过在单个事务中而不是单独地将数组INSERT,UPDATE和DELETE语句发送到数据库来提高数据库性能。&#34;,so是的,它需要在一次交易中完成。

编辑:我还可以从上下文中注入一个约束验证器,并在persistence.xml上禁用JPA验证器,这样我就可以在JPA PrePersist操作之前验证实体列表。但是,这将影响其他不需要批量操作但仍需要验证的实体。啊!几乎就在那里。

1 个答案:

答案 0 :(得分:2)

您可以进行手动验证,只需跳过无效的实体,如下所示:

// in the class inject validator
@Resource
Validator validator;
...

for(TheEntity ent : entities){
     if( validator.validate(ent).size() == 0) {
         // valid - persist
         em.persist(ent);       
     } else {
        // invalid - skip
    }
}