Spring JPA更新并返回更新后的数据[重复]

vfhzx4xs  于 2023-03-02  发布在  Spring
关注(0)|答案(1)|浏览(261)
    • 此问题在此处已有答案**:

Spring Data Repository @Query - Update and return modified entity(4个答案)
两年前关闭了。
如何建立一个JPA方法,当使用JPA查询进行更新时,可以返回更新后的数据?我创建了这样的东西。

@Transactional
@Modifying
@Query("UPDATE User u SET u.isActive = true"
      + " WHERE u.isActive = false AND u.reactivateTime <= currentTime"
      + " AND u.reactivateTime IS NOT null")
int reactivateUser(@Param("currentTime") ZonedDateTime currentTime);

但是,我想要的是返回用户列表。如果我直接将其更改为这样的内容

@Transactional
@Modifying
@Query("UPDATE User u SET u.isActive = true"
      + " WHERE u.isActive = false AND u.reactivateTime <= currentTime"
      + " AND u.reactivateTime IS NOT null")
List<User> reactivateUser(@Param("currentTime") ZonedDateTime currentTime);

它会变成这样的错误。

IllegalStateException: org.hibernate.hql.internal.QueryExecutionRequestException: Not supported for DML operations
ryoqjall

ryoqjall1#

正如您所发现的,仅仅更改方法的返回类型不会导致自动生成的JPA方法返回不同的类型。
问题是,您正在执行批量更新操作,这将在执行时被转换为等价的SQL“update... where”语句,JDBC将返回的唯一数据是更新的行数(顺便说一句,在这种情况下,您应该返回long,而不是int)。
因此,你必须想出其他方法来做这件事。我现在想到两个方法:
1.如果你可以非常确定你将总是更新相对较少的行(比如,最多几百行),那么你可以创建一个方法来选择你想要更新的实体示例,例如:

@Query("SELECT u from User" + " WHERE u.isActive = false AND u.reactivateTime <= currentTime" + " AND u.reactivateTime IS NOT null")
List<User> getUsersToReactivate(@Param("currentTime") ZonedDateTime currentTime);

然后,在JPA存储库接口的具体实现中,

  • 调用方法以检索实体。
  • 通过java代码更新实体
  • 保存实体

例如(我只是输入了这个,没有尝试-语法错误是你的责任):

@Transactional
@Modifying
List<User> reactivateUsers(ZonedDateTime currentTime) {
   List<User> users = getUsersToReactivate(currentTime);
   users.forEach(user -> {
       user.setActive(true);
       save(user);
   ); 
   return users; 
}

1.这样做可能会更具侵入性,但您可以将Date属性添加到名为“lastUpdated”的User类,获取当前日期,将isActive标志更新为true并将“lastUpdated”属性更新为当前日期,然后选择lastUpdate属性为当前日期的实体。

相关问题