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

时间:2013-11-02 20:45:22

标签: java jpa spring-data-jpa nativequery

我有一个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 个答案:

答案 0 :(得分:39)

使用@Query注释的方法执行查询以便从数据库中读取。不要更新数据库。为此,如the documentation所示,您需要将@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);
  

这将触发向方法添加注释的查询,而不是选择查询。

答案 1 :(得分:3)

使用这两个注释

import org.springframework.data.jpa.repository.Modifying;
import org.springframework.transaction.annotation.Transactional;

@Modifying
@Transactional