繁体   English   中英

如何防止 Spring 数据 JPA 中的自动更新?

[英]How to prevent automatic update in Spring Data JPA?

在我的 Spring 启动批处理应用程序中,我从 Tasklet 调用 JPA 存储库 class。 JPA 调用从 DB 中检索特定值(实体对象)。 问题是,如果我更新实体 object 中的某些值,一旦控件退出 Tasklet,即使我没有调用任何保存操作,它也会自动更新到 DB。 如何防止这种情况? 默认 JPA 实现是 Hibernate。

小任务 class

Employee employee = employeeRepository.fetchEmployee(employeeName);
List<Address> addressList = employee.getAddress();
addressList.forEach(e -> e.setStatus(Status.INVALID.toString()));

存储库

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    @Query("select em from Employee em where em.employeeName = :employeeName")
    public Employee fetchEmployee(@Param("employeeName") Long employeeName);
}

实体 class

@Entity
@Table(name = "Employee")
public class Employee implements java.io.Serializable {

    private static final long serialVersionUID = -3769636546619492649L;
    private Long id;
    private List<Address> address;
    private String employeeName;
    
    // Getters and setters
    // @OneToMany mapping to Address
}

即使我没有调用 a.save() 操作,它也会自动将地址表状态更新为“无效”

发生这种情况是因为实体不在分离的 state 中。 在 EJB 中,我们可以通过以下方式做到这一点。

EJB 解决方案

@Query(value = "select * from Employee WHERE EmployeeName = ?1", nativeQuery = true)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public List<Employee> fetchEmployee(String employeeName);

这将使交易关闭。 您对实体所做的更改不会保存在数据库中

Spring JPA

经过一番研究,我发现 JPA 不提供开箱即用的分离功能。

参考: https://github.com/spring-projects/spring-data-jpa/issues/641

为了让它工作,我们可以有一个自定义的 JPA 存储库,它会覆盖分离方法。 此链接中给出了一个示例。

https://www.javaer101.com/en/article/1428895.html

使用深度克隆来解决您的问题。

首先覆盖地址 class 中的克隆方法,如下所示。 注意:请通过添加您的 class 属性来自定义clone()方法的实现。由于您没有提到 class 地址的结构,我已经使用自己定义的 class 属性实现了该解决方案。

地址 class

public class Address {

    private String country;
    private String city;
    private String district;
    private String addressValue;

    public Address() {
        super();

    }

    public Address(String country, String city, String district, String addressValue) {
        super();
        this.country = country;
        this.city = city;
        this.district = district;
        this.addressValue = addressValue;
    }
 //Getters and Setters 

   @Override
    protected Object clone()  {
        try {
            return (Address) super.clone();
        } catch (CloneNotSupportedException e) {
            return new Address(this.getCountry(), this.getCity(), this.getDistrict(),this.getAddressValue());
        }
    }

}

然后重新构建您的 class Tasket,如下所示。

任务组 Class

Employee employee = employeeRepository.fetchEmployee(employeeName);
List<Address> addressList = employee.getAddress();
List<Address> clonedAddressList = new ArrayList<>();
addressList.forEach(address -> clonedAddressList.add((Address)address.clone()) );
clonedAddressList.forEach(address -> address.setStatus(Status.INVALID.toString()));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM