【问题标题】:Transactional(propagation = Propagation.REQUIRES_NEW) not opening a new transaction in private method getting same value passed as parameterTransactional(propagation = Propagation.REQUIRES_NEW) 未在私有方法中打开新事务,获取作为参数传递的相同值
【发布时间】:2020-12-14 02:41:52
【问题描述】:

我正在使用 jpa 实体侦听器类 where 和 spring 数据存储库。在@PreMethod 更新中,如果我使用@Transactional(propagation = Propagation.REQUIRES_NEW),我将直接从数据库中获取数据。如果我在私有方法(getOldEmployee) 上使用相同的 事务注释 called inside @PreMethod 我没有从数据库中获取数据,而是使用相同的最新会话数据不确定为什么会发生这种行为

实体类

@Entity
@Table(name = "Employee")
@EntityListeners({EmployeeListener.class)
public class Employee extends AuditEntity implements Serializable {

}

监听类

 @Component
 public class EmployeeListner{
 
 @Autowired
 EmployeeRepository employeeRepository;

  @PreUpdate
  @Transactional(propagation = Propagation.REQUIRES_NEW)   //if use here I get the employee database value before updating the database
  public void preUpdateEvent(Employee employee) {
    Employee employee=getOldEmployee(employee);
  }


  private Employee getOldEmployee(Employee employee) {     //if inspite of using  @Transactional(propagation = Propagation.REQUIRES_NEW) in @PreMethod if use here I am not getting the database value rather getting latest value
    Optional<Employee> getOldEmployeeOptional =employeeRepository.findById(employee.getId());
    getOldEmployeeOptional  
  }
}

【问题讨论】:

  • @Transactional 与 Spring AOP 将不起作用。它仅适用于公共方法和外部调用的方法。这是因为代理被用于应用 AOP。
  • @M.Deinum 我尝试将私有方法设为公开,但在 getOldEmployee() 方法上应用 @Transactional(propagation = Propagation.REQUIRES_NEW) 调用employeeRepository.findById(employee.getId( ));只给出不是从数据库传递的最新值
  • @M.Deinum 但是如果我在 preUpdateEvent 方法上应用@Transactional(propagation = Propagation.REQUIRES_NEW) 它可以调用employeeRepository.findById(employee.getId());正在从数据库中给我价值
  • 如前所述,因为它是内部方法调用,所以也不起作用。

标签: java spring spring-boot spring-data-jpa spring-transactions


【解决方案1】:

Spring 仅在 public 方法上应用事务设置,在其他情况下忽略设置。
来自 Spring 文档:

当使用代理时,你应该应用@Transactional注解 仅适用于具有公共可见性的方法。

【讨论】:

  • 我也尝试过公开方法,但结果相同,我得到的是相同的新值,而不是应该来自数据库的旧值
  • 不在我的代码中,但如果我深入研究 spring readOnly=true 的 simpleJpaRepository,那里提到了 @Transactional(readOnly = true) public class SimpleJpaRepository implements JpaRepositoryImplementation
  • 无论如何,当使用 Propagation.REQUIRES_NEW 时,它确实跨越了一个新事务(如果数据库支持),这意味着任何错误都不会影响外部事务。您的问题有所不同:您的 JPA 会话只有一个对象(修改后的对象)在内存中(或者可能已刷新到数据库但尚未提交)。您想要的是使用不同的会话来加载原始值或尝试 session.refresh (这会覆盖对实体所做的更改)。使用 Hibernate,您还可以驱逐对象并重新查询(从 DB 重新加载),我希望 JPA 也可以实现类似的功能。
猜你喜欢
  • 2017-11-18
  • 2013-03-23
  • 2020-06-23
  • 2011-10-05
  • 1970-01-01
  • 1970-01-01
  • 2019-07-12
  • 1970-01-01
  • 2021-10-14
相关资源
最近更新 更多