我在使用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')]
。
答案 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'))