簡體   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