JPA 存储库保存:插入约束冲突后继续保存



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

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

人民数据库.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 条目中的空 id(发生异常后不要刷新会话(">

如何避免这种行为?如何清理会话或启动新会话?

提前非常感谢 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);
}
}

这在我的测试中工作得很好。你觉得怎么样?

单个事务

原因是所有插入都发生在一个事务中。由于此事务是原子的,它要么完全成功,要么失败,因此两者之间没有任何内容。

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

public interface PeopleRespository {
boolean existsByLastnameAndFirstname(String lastname, String firstname);
}

然后:

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

每人一次交易

另一种选择确实是为每个人开始新的交易。但我不确定它会更有效率,因为创建交易需要额外的成本。

最新更新