使用join批量更新spring数据jpa

时间:2017-09-08 14:22:36

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

我在使用JPA 2.1进行批量更新(spring-data-jpa)时遇到了麻烦。

根据文件:

  

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

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

但我需要更新的实体与另一个实体有@ManyToOne的关系。

@Entity
@Table(name = "usuarios", indexes = {
    @Index(name = "idx_usuarios_rut", columnList = "rut")
    ,@Index(name = "idx_usuarios_email", columnList = "email")})
public class User extends BaseEntity implements UserDetails {
    ...

    @NotNull(message = "Debe seleccionar un nivel")
    @ManyToOne(fetch = FetchType.LAZY)
    public Role getRole() {
        return role;
    }
}

所以我的UPDATE是:

@Modifying
@Transactional
@Query("update User u set u.password = ?2 where u.company = ?1 and u.role.name not in ('ROLE_ADMIN', 'ROLE_ROOT')")
int updatePasswordForAll(Company company, String password);

生成的原始查询为update usuarios cross join set password=? where company_id=? and (nombre not in ('ROLE_ADMIN' , 'ROLE_ROOT')),因此我得到com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual ...

我做错了什么?

我试过

@Query("update User u set u.password = ?2 join u.role r where u.company = ?1 and r.name not in ('ROLE_ADMIN', 'ROLE_ROOT')")

但这是一个形成错误的更新句org.hibernate.QueryException: node to traverse cannot be null! [update cl.arvisoft.mantenimiento.jpa.User u set u.password = ?2 join u.role r where u.company = ?1 and r.name not in ('ROLE_ADMIN', 'ROLE_ROOT')]

1 个答案:

答案 0 :(得分:3)

在JPQL中,您无法在执行更新操作时加入实体(请参阅reference)。

要解决这种情况,请尝试使用子选择,类似这样(未经测试):

update 
    User u 
set 
    u.password = ?2 
where 
    u.company = ?1 and 
    u.role in (select r from Role r where r.name not in ('ROLE_ADMIN', 'ROLE_ROOT'))