Spring Data JPA:如何优雅地更新模型?
Spring Data JPA: How to update a model elegantly?
我的模型是这样的:
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name="email")
private String email;
@Column(name = "weblink")
private String webLink;
//getter & setter
}
我们通过http请求收集表单或移动数据,springmvc会将这些数据做成一个Model like user
例如,我有这样一个请求:
http://localhost:8080/update?id=1919&email=xx@google.com
在控制器中,请求url及其参数将自动转换为User
对象。
@RequestMapping(method = RequestMethod.GET, value = "/update0")
public User update(@ModelAttribute("User") User user){
System.out.println(user.getId());
System.out.println(user.getEmail());
System.out.println(user.getWebLink());
return userRepository.save(test);
}
如果我在mysql中有一条id为1919的记录,并且列(id,email,weblik)都有值。
如你所见,通过网络或手机传递的用户对象有两个属性
http://localhost:8080/update?id=1919&email=xx@google.com
id 和 email 有值而 weblink 没有。
因此,如果我执行 save
方法,电子邮件列将更新为 xx@google.com
,weblik 字段也将更新为 NULL
,但我没有想更新这个字段,我只想更新电子邮件字段。
我有两种方法可以解决这个问题,但都不太优雅。
5.1 先加载用户对象并更新
User userExist = userRepository.findOne(user.getId());
userExist.setEmail(user.getEmail());
//or using
//BeanUtil.copyProprty(formDto,modle)
userRepository.save();
5.2 使用 @DynamicUpdate
,但它不起作用。
有没有其他方法可以更新用户模型并且不做一些额外的工作。
提前致谢。
最简单的方法是适当设置控制器方法:
@RequestMapping(value = "/users/{user}", method = RequestMethod.PATCH)
public … updateUser(@ModelAttribute User user) { … }
根据reference documentation调用此方法时会发生以下步骤:
- 需要获取
User
的实例。这基本上需要从 String
到 User
的 Converter
注册到 Spring MVC 以将从 URI 模板中提取的路径段转换为 User
。如果你是使用 Spring 数据并启用其 reference documentation 中所述的 Web 支持,这将开箱即用。
- 获取现有实例后,请求数据将绑定到现有对象。
- 绑定的对象将被传递到方法中。
其他提示
- 不要使用
GET
作为更新的 HTTP 方法。 GET
被定义为安全操作(无副作用),更新不是。 PATCH
是此处的正确方法,因为它被定义为允许对现有资源进行部分更新。
- 要将表单数据提交到
PUT
和 PATCH
请求中,您需要按照 here. I filed an issue with Spring Boot 所述向应用程序注册一个 HttpPutFormContentFilter
以默认注册。
首先我要说 @Oliver Gierke
的 Patch
解决方案真的很棒。
而在我之前的项目中,我的解决方案是:
1、创建抽象class实现JpaRepository
,实现save()
功能
2. 在保存函数中,从数据库中获取实体。它不存在,只是保存它。否则,使用反射从更新的实体中获取所有 NOT NULL 字段,并从数据库中设置到实体中。 (和你做的很相似,不过我是为了所有的保存功能而做的)
我的模型是这样的:
@Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column(name="email") private String email; @Column(name = "weblink") private String webLink; //getter & setter }
我们通过http请求收集表单或移动数据,springmvc会将这些数据做成一个Model like user
例如,我有这样一个请求:
http://localhost:8080/update?id=1919&email=xx@google.com
在控制器中,请求url及其参数将自动转换为
User
对象。@RequestMapping(method = RequestMethod.GET, value = "/update0") public User update(@ModelAttribute("User") User user){ System.out.println(user.getId()); System.out.println(user.getEmail()); System.out.println(user.getWebLink()); return userRepository.save(test); }
如果我在mysql中有一条id为1919的记录,并且列(id,email,weblik)都有值。
如你所见,通过网络或手机传递的用户对象有两个属性
http://localhost:8080/update?id=1919&email=xx@google.com
id 和 email 有值而 weblink 没有。
因此,如果我执行
save
方法,电子邮件列将更新为xx@google.com
,weblik 字段也将更新为NULL
,但我没有想更新这个字段,我只想更新电子邮件字段。我有两种方法可以解决这个问题,但都不太优雅。
5.1 先加载用户对象并更新
User userExist = userRepository.findOne(user.getId()); userExist.setEmail(user.getEmail()); //or using //BeanUtil.copyProprty(formDto,modle) userRepository.save();
5.2 使用
@DynamicUpdate
,但它不起作用。有没有其他方法可以更新用户模型并且不做一些额外的工作。
提前致谢。
最简单的方法是适当设置控制器方法:
@RequestMapping(value = "/users/{user}", method = RequestMethod.PATCH)
public … updateUser(@ModelAttribute User user) { … }
根据reference documentation调用此方法时会发生以下步骤:
- 需要获取
User
的实例。这基本上需要从String
到User
的Converter
注册到 Spring MVC 以将从 URI 模板中提取的路径段转换为User
。如果你是使用 Spring 数据并启用其 reference documentation 中所述的 Web 支持,这将开箱即用。 - 获取现有实例后,请求数据将绑定到现有对象。
- 绑定的对象将被传递到方法中。
其他提示
- 不要使用
GET
作为更新的 HTTP 方法。GET
被定义为安全操作(无副作用),更新不是。PATCH
是此处的正确方法,因为它被定义为允许对现有资源进行部分更新。 - 要将表单数据提交到
PUT
和PATCH
请求中,您需要按照 here. I filed an issue with Spring Boot 所述向应用程序注册一个HttpPutFormContentFilter
以默认注册。
首先我要说 @Oliver Gierke
的 Patch
解决方案真的很棒。
而在我之前的项目中,我的解决方案是:
1、创建抽象class实现JpaRepository
,实现save()
功能
2. 在保存函数中,从数据库中获取实体。它不存在,只是保存它。否则,使用反射从更新的实体中获取所有 NOT NULL 字段,并从数据库中设置到实体中。 (和你做的很相似,不过我是为了所有的保存功能而做的)