[entity]实体的[column]属性被修改,但不会更新,因为该属性是不可变的

问题描述 投票:0回答:1

以前曾有人问过这个问题,但我还没有找到任何适合我的用例的答案。 我创建了一个简化的玩具示例来解释我的问题。 想象我们有一个

Customer
Purchase
实体:

@Entity
public class Customer implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    @Column(name = "first_name")
    private String firstName;
    @Column(name = "last_name")
    private String lastName;

    protected Customer() {}

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
@Entity
public class Purchase {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    @Column(name = "item_name")
    private String itemName;
    @Column(name = "first_name")
    private String firstName;
    @Column(name = "last_name")
    private String lastName;

    @ManyToOne
    @JoinColumns({
        @JoinColumn(updatable=false, insertable=false, name="first_name", referencedColumnName="first_name"),
        @JoinColumn(updatable=false, insertable=false, name="last_name", referencedColumnName="last_name")
    })
    Customer customer;
    public Customer getCustomer() { return customer; }
    public void setCustomer(Customer customer) { this.customer = customer; }

    public void setID(Long id) { this.id = id; }
    public Long getID() { return this.id; }

    protected Purchase() { }

    public Purchase(String itemName, String firstName, String lastName) {
        this.itemName = itemName;
        this.firstName = firstName;
        this.lastName = lastName;
    }

}

如您所见,购买使用两列连接到客户:客户的名字和姓氏(我知道这有点人为,因为最好连接客户 ID)。 问题是当我尝试更新现有购买时。如果购买详细信息发生更改,我会创建一个全新的购买,设置此新购买的 ID 字段,然后保存新购买,该新购买将覆盖旧购买,因为它们具有相同的 ID。

customerRepository.save(new Customer("firstName", "lastName"));
purchaseRepository.save(new Purchase("itemName", "firstName", "lastName"));

Purchase p1 = purchaseRepository.findAll().get(0);
Purchase p2 = new Purchase("updatedItemName", "firstName", "lastName");
p2.setID(p1.getID());
purchaseRepository.save(p2);

但是,这总是会产生此警告:

2022-07-22 21:04:22.088  WARN 46139 --- [           main] o.h.p.entity.AbstractEntityPersister     : HHH000502: The [customer] property of the [com.example.accessingdatajpa.Purchase] entity was modified, but it won't be updated because the property is immutable.

我需要帮助来防止出现此警告。

我知道我可以用

p1
的数据更新
p2
,但问题是在我的实际代码中,购买有很多字段,如果可能的话,我想避免手动设置每个字段。 如果有人有更好的解决方案,我可以根据新记录更新旧记录(不指定要更新的列的名称),我很想看到该解决方案。

java spring-boot jpa spring-data-jpa spring-data
1个回答
0
投票

根据两种情况,可以通过两种方式解决。

场景 1: 客户属性未直接映射到数据库列,而任何其他列均未从中派生。

此场景的解决方案:删除

updatable=false, insertable=false

列定义。您的代码应如下所示:

@ManyToOne
@JoinColumns({
    @JoinColumn(name="first_name", referencedColumnName="first_name"),
    @JoinColumn(name="last_name", referencedColumnName="last_name")
})
private Customer customer;

场景 2: 客户属性直接映射到数据库列,而任何其他列均从中派生。

此场景的解决方案:修改Customer列添加新列,

@ManyToOne(targetEntity = Customer.class, fetch = FetchType.EAGER)
@JoinColumns({
    @JoinColumn(name="first_name", referencedColumnName="first_name"),
    @JoinColumn(name="last_name", referencedColumnName="last_name")
})
private Customer customer;

@Column(updatable=false, insertable=false, name = "customer_id")
private long customerId;

希望这对您有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.