【问题标题】:Spring JPA Update and Return the Updated Data [duplicate]Spring JPA更新并返回更新的数据[重复]
【发布时间】:2020-04-28 04:07:51
【问题描述】:

当使用 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

【问题讨论】:

  • 更新操作没有获取任何数据

标签: java spring spring-boot jpa spring-data-jpa


【解决方案1】:

正如您所发现的,仅更改方法的返回类型不会导致自动生成的 JPA 方法返回不同的类型。

问题是您正在执行批量更新操作。这将在执行时变成等效的 SQL“update...where”语句,JDBC 返回的唯一数据是更新的行数。 (顺便说一句,在这种情况下,您应该返回一个 long,而不是 int)。

因此,您必须设计一些其他方法来做到这一点。 副手,我可以想到两种方法:

  1. 如果您可以确定您将始终更新相对较少的行数(例如,最多几百行),那么您可以创建一个方法来选择您要更新的实体实例,例如

    @Query("从用户中选择你" + "在哪里 u.isActive = false AND u.reactivateTime

然后,在 JPA Repository 接口的具体实现中,

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

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

@Transactional
@Modifying
List<User> reactivateUsers(ZonedDateTime currentTime) {
   List<User> users = getUsersToReactivate(currentTime);
   users.forEach(user -> {
       user.setActive(true);
       save(user);
   ); 
   return users; 
}
  1. 这可能更具侵入性,但您可以向名为“lastUpdated”的用户类添加一个 Date 属性,获取当前日期,将 isActive 标志更新为 true,并将“lastUpdated”属性更新为当前日期,然后选择lastUpdate 属性为当前日期的实体。

【讨论】:

    猜你喜欢
    • 2016-07-28
    • 2014-06-13
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多