Java Spring启动-Hibernate,在异常时回滚成功保存

Java Spring启动-Hibernate,在异常时回滚成功保存,java,spring,hibernate,spring-boot,spring-transactions,Java,Spring,Hibernate,Spring Boot,Spring Transactions,我正在使用SpringBootV2.1.3.RELEASE和HibernateV5.3.6构建一个应用程序 之前,我问了一个关于如何跨多个服务/存储库使用@Transactional回滚的问题。我通过使用@OneToOne和@OneToMany注释将我的实体链接在一起,得到了我所需要的东西 现在我面临一个新问题。在单个服务的函数中,我保存两个单独的实体列表。一个列表保存,另一个列表由于唯一密钥约束冲突而失败。自im测试以来,预计这将失败 但是,我还没有弄清楚如何用@Transactional注释

我正在使用SpringBootV2.1.3.RELEASE和HibernateV5.3.6构建一个应用程序

之前,我问了一个关于如何跨多个服务/存储库使用@Transactional回滚的问题。我通过使用@OneToOne和@OneToMany注释将我的实体链接在一起,得到了我所需要的东西

现在我面临一个新问题。在单个服务的函数中,我保存两个单独的实体列表。一个列表保存,另一个列表由于唯一密钥约束冲突而失败。自im测试以来,预计这将失败

但是,我还没有弄清楚如何用@Transactional注释我的服务或方法,这样当第二个列表无法保存时,它也会回滚第一个列表的任何成功保存

例如:

@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
protected void saveLists() {
    List<Object> list1 = this.repository.getListOne();
    List<Object> list2 = this.repository.getListTwo();

    //Loop through list one and do some manipulation
    //Loop through list two and do some manipulation

    this.repository.saveAll(list1); // this saves all successfully
    this.repository.saveAll(list2); // this has unique key exception

    // rollback both list1 and list2 changes
}
@Transactional(propagation=propagation.REQUIRES\u NEW,rollboor=Exception.class)
受保护的无效存储列表(){
List list1=this.repository.getListOne();
List list2=this.repository.getListTwo();
//循环浏览列表1并进行一些操作
//循环浏览列表2并进行一些操作
this.repository.saveAll(list1);//这将成功保存所有
this.repository.saveAll(list2);//这有唯一的密钥异常
//回滚列表1和列表2的更改
}
在上面的示例中,list1中的数据成功保存,并在抛出list2中的异常后显示在数据库中

我认为,由于它们在相同的服务和相同的方法中,使用相同的存储库,它们将使用相同的事务,并且Hibernate不会提交事务,直到它使此方法没有错误为止

但事实似乎并非如此。由于列表1的数据正在提交而不是回滚

@Transactional注释是否有我遗漏的地方?
如何使两个保存作为单个事务工作,并在从任一保存引发错误时同时回滚这两个保存?

您只需使用@Transactional注释在控制器中调用的服务的方法,而不是此方法。
或者您可以用@Transactional注释服务类,因为@Transactional不适用于私有或受保护的方法,您的方法应该是公共的。 为什么?
因为spring应该创建一个代理来处理事务划分和行为。由于无法代理受保护或私有的方法,因此您的注释将被忽略。

该方法最初是私有的,因为我不希望任何人直接从服务外部调用此方法。Spring不允许将@Transactional放在私有方法上。它必须是公共的、受保护的或包私有的。我认为这不会有什么区别,因为我认为事务将在调用该函数时开始,并在函数完成时提交。@NathanHughes所以,如果说,我在调用服务的控制器端点上添加了
@Transactional
注释,那么事务行为会起作用吗?或者我应该用
@Transactional
注释我的JPA Repository类吗?我想一个快速的解决方案是,不要执行两个保存操作,而是将两个列表合并成一个,然后一次保存一个列表。然后,如果任何记录失败,整个事务都应该回滚。但这并不能帮助我理解为什么我当前的实现无法工作。