【发布时间】:2014-03-11 12:07:17
【问题描述】:
我正在使用带有 RESTful 接口的 Spring-Data JPA 和 Spring-MVC。我正在尝试实现一个基本的 CRUD 控制器。我在找出实施“更新”的最佳方式时遇到了一些困难。
我的基本控制器方法很简单:
@RequestMapping( method=RequestMethod.POST, value="updateUser", produces=MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public User update( @RequestBody final User user){
userRepository.save(user);
return user;
}
但是,这似乎只提供了“创建”,而不是“更新”。每次调用该方法时,都会在数据库中创建一个新用户,即使我在 JSON 对象中指定了用户 PK。
快速查看SimpleJpaRepository 类,只要“版本”字段丢失,它就会创建一个新对象。但是,如果我强制“版本”字段有一个值,我会得到一个异常(不足为奇):
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.ia.domain.User#5]
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:303)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:151)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:76)
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:914)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:898)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:902)
at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:889)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
我意识到一种选择是首先查询数据库中现有的用户对象(基于提交的 PK),然后复制所有字段,然后保存该对象,但这似乎不是正确的方法。我想一定有办法让我“合并”我的 User 对象并更新它,但我不完全确定如何。
有简单的方法吗?
【问题讨论】:
-
考虑先查找再更新
-
@Koitoer - 我绝对可以先查找然后更新,但是我需要复制 POSTed JSON 对象中的所有字段,并且不确定是否有快速/简单/高效这样做的方式。
标签: java json rest spring-mvc spring-data-jpa