Spring Data JPA删除本地查询时抛出异常

25

我有一个User实体和一个Role实体。它们的关系定义如下:

@OneToMany
@JoinTable(name="USER_ROLES", inverseJoinColumns=@JoinColumn(name="ROLE_ID"))
private List<Role> roles = null; 

现在,当我删除一个角色时,需要将拥有该角色的所有用户的角色都删除。通常,您会通过查找所有拥有此角色的用户,从列表中删除角色并保存用户来完成此操作。但是,当可能有超过一百万个用户时,我不想在应用程序中循环遍历这么多实体。因此,我想使用本机查询从USER_ROLES联接表中删除行。我尝试将以下内容添加到我的存储库:

@Query(value="DELETE FROM user_roles WHERE role_id = ?1", nativeQuery=true)
public void deleteRoleFromUsersWithRole(Long roleId);

但是,当我这样做时,日志中会出现以下内容:

[EL Fine]: sql: 2013-11-02 14:27:14.418--ClientSession(707349235)--Connection(2096606500)--Thread(Thread[http-bio-8080-exec-4,5,main])--DELETE FROM user_roles WHERE role_id = ?
   bind => [1000110139999999953]
[EL Fine]: sql: 2013-11-02 14:27:14.478--ClientSession(707349235)--Thread(Thread[http-bio-8080-exec-4,5,main])--SELECT 1
[EL Warning]: 2013-11-02 14:27:14.482--UnitOfWork(1795045370)--Thread(Thread[http-bio-8080-exec-4,5,main])--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: No results were returned by the query.
Error Code: 0
Call: DELETE FROM user_roles WHERE role_id = ?
    bind => [1000110139999999953]
Query: DataReadQuery(sql="DELETE FROM user_roles WHERE role_id = ?")

我不理解 No results were returned by the query. 的含义。记录已经从数据库中删除,但这个异常导致一切都崩溃了。

请问有人可以告诉我在这里哪里出错了吗?

2个回答

57

使用 @Query 注解的方法执行查询操作以从数据库中读取数据,而不是更新数据库。如 文档 所示,要想更新数据,你需要在方法上添加 @Modifying 注解:

以上所有部分都描述了如何声明查询以访问给定的实体或实体集合。当然,您可以使用第1.3节“Spring Data仓库的自定义实现”的工具来添加自定义修改行为。由于此方法可用于全面的自定义功能,因此您可以通过在查询方法上注释 @Modifying 来实现执行实际上只需要参数绑定的修改查询:

示例 2.13. 声明操作查询

@Modifying
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);

这将触发附注在该方法上的查询,将其作为更新查询而不是选择查询。


9
啊,我对Spring Data和JPA还不太熟悉。我想我应该花更多时间阅读文档。我需要注意的是,为了使其正常工作,我还不得不添加@Transactional注释。感谢您的帮助。 - dnc253
这个int在这里返回什么? - soumya sambit Kunda
https://docs.oracle.com/javaee/7/api/javax/persistence/Query.html#executeUpdate-- - JB Nizet
为什么这个不支持删除语句? - Bhargav Patel

9
请使用这两个注解。
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.transaction.annotation.Transactional;

@Modifying
@Transactional

6
这个答案并没有提供任何已被采纳的答案和@dnc253对其的评论所没有提到的内容。 - chrisis
请问在哪里应该使用这个注解? - Because i hate myself
它允许您将事务管理的责任委托给Spring框架。当调用带有@Transactional注解的方法时,Spring将自动开始一个事务,在成功时提交它,或在出现异常时回滚它。这消除了手动处理事务的需要。 - undefined
你可以使用@Transactional注解来定义自定义的回滚规则。这允许你指定在什么条件下事务应该被回滚。例如,你可以指定如果抛出特定的异常,事务应该被回滚。 - undefined
@Transactional注解与各种数据源(如关系型数据库、JMS和JPA)无缝集成,使您能够以一致的方式使用不同的持久化技术。 - undefined
我相信这已经为您澄清了事情。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接