java - JPA-存储库保存 : Proceed saving after insert Constraint violation

标签 java hibernate jpa spring-data-jpa unique-constraint

我正在使用 JPA 存储库将简单的数据对象保存到数据库中。为了避免重复,我在多个字段上创建了唯一约束。如果现在应该保 stub 据唯一字段/约束的重复项,我想捕获异常,记录该对象,并且应用程序应该继续并保存下一个对象。但在这里我总是得到这个异常:“org.hibernate.AssertionFailure:de.test.PeopleDBO条目中的null id(发生异常后不要刷新 session )”。

总的来说,我了解 hibernate 在做什么,但是我如何恢复 session 或启动新 session 以继续保存下一个数据对象。请看下面的代码:

PeopleDBO.java

@Entity
@Data
@Table(
        name = "PEOPLE", 
        uniqueConstraints = {@UniqueConstraint(columnNames = {"firstname", "lastname"}})
public class PeopleDBO {

    public PeopleDBO(String firstname, String lastname) {
        this.firstname = firstname;
        this.lastname = lastname;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String firstname;

    private String lastname;

}

测试:

public void should_save_people_and_ignore_constraint_violation(){
    final List<PeopleDBO> peopleList = Arrays.asList(
        new PeopleDBO("Georg","Smith"),
        new PeopleDBO("Georg","Smith"),
        new PeopleDBO("Paul","Smith")
    );

    peopleList.forEach(p -> {
        try {
            peopleRepository.save(p);
        } catch (DataIntegrityViolationException e) {
            log.error("Could not save due to constraint violation: {}",p);
        }
    }

    Assertions.assertThat(peopleRepository.count()).isEqualTo(2);
}

问题是,随着拯救第二个人,唯一约束被违反。错误日志发生,并且在下次调用 peopleRepository.save() 时抛出上面提到的异常:

“org.hibernate.AssertionFailure:de.test.PeopleDBO 条目中的 null id(发生异常后不刷新 session )”

我怎样才能避免这种行为?我如何清理 session 或开始新 session ?

提前非常感谢 d.

--------- 编辑/新想法 ------ 我刚刚尝试了一些事情,发现我可以实现 PeopleRepositoryImpl,如下所示:

@Service
public class PeopleRepositoryImpl {

    final private PeopleRepository peopleRepository;

    public PeopleRepositoryImpl(PeopleRepository peopleRepository) {
        this.peopleRepository = peopleRepository;
    }

    @Transactional
    public PeopleDBO save(PeopleDBO people){
        return peopleRepository.save(people);
    }
}

这在我的测试中运行得很好。 ...你觉得怎么样?

最佳答案

一笔交易

原因是所有插入都发生在一个事务中。由于此事务是原子,它要么完全成功,要么失败,没有中间状态。

最干净的解决方案是在尝试插入之前检查 People 是否存在:

public interface PeopleRespository {

    boolean existsByLastnameAndFirstname(String lastname, String firstname);
}

然后:

if (!peopleRepository.existsByLastnameAndFirstname(p.getLastname, p.getFirstname)) {
    peopleRepository.save(p);
}

每人一笔交易

另一种选择确实是为每个人启动一项新交易。但我不确定它会更有效,因为创建交易会产生额外的成本。

关于java - JPA-存储库保存 : Proceed saving after insert Constraint violation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60188653/

相关文章:

hibernate - EntityManager.merge(x) 导致 "select"查询数据库

spring - JPA 通过多条件查找

java - BigDecimal 类型列的默认值的 JPA 注释

java - Micronaut:无法使用 junit 测试重定向响应

java - 使用 Java 的 Quartz 作业调度程序,卡在待机模式而不执行作业

mysql - Hibernate 标识符名称对于 MySQL 索引来说太长

java - transient 变量的注解@Basic

java - Android 多点触控 - 不规则手指跟踪

c# - 工厂模式很多参数需要提示

java - 在类的 DAO 中使用不同的类