如何在Spring Data中精美地更新JPA实体?

所以我查看了有关使用Spring Data的JPA的各种教程,这在很多场合都有所不同,我不太确定正确的方法是什么。

假设有以下实体:

package stackoverflowTest.dao; import javax.persistence.*; @Entity @Table(name = "customers") public class Customer { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private long id; @Column(name = "name") private String name; public Customer(String name) { this.name = name; } public Customer() { } public long getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 

我们还有一个DTO,它在服务层中检索,然后交给控制器/客户端。

 package stackoverflowTest.dto; public class CustomerDto { private long id; private String name; public CustomerDto(long id, String name) { this.id = id; this.name = name; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 

所以现在假设客户想要在webui中更改他的名字 – 然后会有一些控制器操作,其中将有更新的DTO,其中包含旧ID和新名称。

现在我必须将这个更新的DTO保存到数据库中。

目前不可能更新现有客户(除了删除数据库中的条目并使用新的自动生成的ID创建新的Cusomter)

然而,因为这是不可行的(特别是考虑到这样的实体可能有数百个关系) – 所以我脑子里有两个直接的解决方案:

  1. 在Customer类中为id创建一个setter – 从而允许设置id,然后通过相应的存储库保存Customer对象。

要么

  1. 将id字段添加到构造函数中,每当您想要更新客户时,始终使用旧id创建一个新对象,但是其他字段的新值(在这种情况下只是名称)

所以我的问题是,有一般规则如何做到这一点? 任何可能我解释的2种方法的缺点是什么?

甚至更好的@Tanjim Rahman回答你可以使用Spring Data JPA使用方法T getOne(ID id)

 Customer customerToUpdate = customerRepository.getOne(id); customerToUpdate.setName(customerDto.getName); customerRepository.save(customerToUpdate); 

是更好的因为getOne(ID id) 只获取一个引用 (代理)对象,并且不从DB中获取它。 在这个引用上你可以设置你想要的东西,在save()它只会像你期望的那样只做一个SQL UPDATE语句。 比较当你调用find()像@Tanjim Rahmans一样回答spring数据JPA会做一个SQL SELECT来从数据库中物理地获取实体,当你刚刚更新时,你不需要它。

简单的JPA更新..

 Customer customer = em.find(id, Customer.class); //Consider em as JPA EntityManager customer.setName(customerDto.getName); em.merge(customer); 

这更像是一个对象初始化问题,而不是一个jpa问题,两种方法都可以工作,你可以同时拥有它们,通常如果在使用构造函数参数的实例化之前数据成员值已经准备就绪,如果这个值可能是实例化后更新你应该有一个setter。

如果您需要直接使用DTO而不是实体,那么您应该检索现有的 Customer实例并将更新的字段从DTO映射到该实例。

 Customer entity = //load from DB //map fields from DTO to entity 

我到处都看到嘿,我无法用jpa更新相同的记录。 它不受支持。 我告诉你一件事,如果你只是在html中隐藏变量并将其绑定到现有的记录id字段,然后当你发布表单并通过该id获取记录然后只保存发布的记录对象,它保存到现有记录。

所以关键是在隐藏字段中获取现有记录ID