首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JPA:只更新特定字段

JPA:只更新特定字段
EN

Stack Overflow用户
提问于 2015-01-07 11:21:37
回答 7查看 121.6K关注 0票数 85

是否有一种方法只更新实体对象的某些字段(),使用Spring 中的save方法

例如,我有这样一个JPA实体:

代码语言:javascript
复制
@Entity
public class User {

  @Id
  private Long id;

  @NotNull
  private String login;

  @Id
  private String name;

  // getter / setter
  // ...
}

用它的CRUD回购:

代码语言:javascript
复制
public interface UserRepository extends CrudRepository<User, Long> { }

Spring 中,我有一个控制器,它获取一个User对象来更新它:

代码语言:javascript
复制
@RequestMapping(value = "/rest/user", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<?> updateUser(@RequestBody User user) {

   // Assuming that user have its id and it is already stored in the database,
   // and user.login is null since I don't want to change it,
   // while user.name have the new value

   // I would update only its name while the login value should keep the value 
   // in the database
   userRepository.save(user);

   // ...
}

我知道我可以使用findOne加载用户,然后更改它的名称并使用save更新它.但是,如果我有100个字段,并且我想更新其中的50个字段,那么每个值的更改都会非常恼人。

有没有办法告诉您“在保存对象时跳过所有空值”之类的内容?

EN

回答 7

Stack Overflow用户

发布于 2015-01-09 13:59:42

我也有同样的问题,正如迪金先生指出的,答案是不,你不能使用保存。主要问题是Spring数据不知道如何处理空值。空值是未设置,还是由于需要删除而设置?

现在从您的问题中判断,我假设您也有与我相同的想法,即保存将允许我避免手动设置所有更改的值。

那么,是否有可能避免所有曼纽尔映射呢?好吧,如果你选择遵守“空”总是意味着“不设置”的约定,并且你有原始的模型id,那么是的。通过使用Springs BeanUtils,您可以避免任何映射。

你可以这样做:

  1. 读取现有对象
  2. 使用BeanUtils复制值
  3. 保存对象

现在,Spring的BeanUtils实数不支持不复制空值,因此它将覆盖退出模型对象上没有设置空值的所有值。幸运的是,这里有一个解决方案:

如何使用values框架BeanUtils copyProperties忽略空值?

所以把这一切放在一起,你最终会得到这样的结果

代码语言:javascript
复制
@RequestMapping(value = "/rest/user", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<?> updateUser(@RequestBody User user) {

   User existing = userRepository.read(user.getId());
   copyNonNullProperties(user, existing);
   userRepository.save(existing);

   // ...
}

public static void copyNonNullProperties(Object src, Object target) {
    BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
}

public static String[] getNullPropertyNames (Object source) {
    final BeanWrapper src = new BeanWrapperImpl(source);
    java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

    Set<String> emptyNames = new HashSet<String>();
    for(java.beans.PropertyDescriptor pd : pds) {
        Object srcValue = src.getPropertyValue(pd.getName());
        if (srcValue == null) emptyNames.add(pd.getName());
    }
    String[] result = new String[emptyNames.size()];
    return emptyNames.toArray(result);
}
票数 48
EN

Stack Overflow用户

发布于 2016-12-17 21:09:22

使用JPA,您可以这样做。

代码语言:javascript
复制
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaUpdate<User> criteria = builder.createCriteriaUpdate(User.class);
Root<User> root = criteria.from(User.class);
criteria.set(root.get("lastSeen"), date);
criteria.where(builder.equal(root.get("id"), user.getId()));
session.createQuery(criteria).executeUpdate();
票数 30
EN

Stack Overflow用户

发布于 2018-10-12 08:06:44

你可以写这样的东西

代码语言:javascript
复制
@Modifying
    @Query("update StudentXGroup iSxG set iSxG.deleteStatute = 1 where iSxG.groupId = ?1")
    Integer deleteStudnetsFromDeltedGroup(Integer groupId);

或者,如果只想更新已修改的字段,则可以使用注释。

代码语言:javascript
复制
@DynamicUpdate

代码示例:

代码语言:javascript
复制
@Entity
@Table(name = "lesson", schema = "oma")
@Where(clause = "delete_statute = 0")
@DynamicUpdate
@SQLDelete(sql = "update oma.lesson set delete_statute = 1, "
        + "delete_date = CURRENT_TIMESTAMP, "
        + "delete_user = '@currentUser' "
        + "where lesson_id = ?")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27818334

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档