【问题标题】:Bulk update over spring data jpa with join使用连接批量更新 spring 数据 jpa
【发布时间】:2018-02-17 12:15:12
【问题描述】:

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

根据文档:

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')]。

【问题讨论】:

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


    【解决方案1】:

    在 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'))
    

    【讨论】:

    • 感谢@Cepr0,现在生成的原生更新语句是update usuarios set password=? company_id=?和 (role_id in (select role1_.id from roles role1_ where role1_.nombre not in ('ROLE_ADMIN' , 'ROLE_ROOT')))。
    猜你喜欢
    • 2019-05-02
    • 2021-08-13
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    相关资源
    最近更新 更多