JPQL DELETE语句JOIN语法报错:关联User与Nickname实体时出错
JPA DELETE语句中JOIN语法的问题
实体代码
User.java
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Long id; private String username; @OneToMany(mappedBy = "user", fetch = FetchType.EAGER) private List<Nickname> nicknames; }
Nickname.java
@Getter @Setter @NoArgsConstructor @AllArgsConstructor @Entity @Table(name = "nickname") public class Nickname { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String value; @ManyToOne @JoinColumn(name = "user_id") private User user; @Override public String toString() { return "Nickname{" + "id=" + id + ", value='" + value + '\'' + '}'; } }
仓库接口代码
public interface NicknameRepository extends JpaRepository<Nickname, Long> { @Transactional @Modifying // @Query("DELETE FROM Nickname n WHERE n.value = :value AND n.user.username = :username") @Query("DELETE FROM Nickname n JOIN n.user u where n.value = :value AND u.username = :username") void deleteNicknameByValue(@Param("username") String username, @Param("value") String value); }
报错信息
java.lang.IllegalArgumentException: org.hibernate.query.SyntaxException: At 1:23 and token 'JOIN', mismatched input 'JOIN', expecting one of the following tokens: <EOF>, WHERE [DELETE FROM Nickname n JOIN n.user u where n.value = :value AND u.username = :username]
问题原因及解决方法
JPQL的DELETE语句语法规范不允许在DELETE FROM子句后直接使用JOIN,这是导致报错的核心原因。你可以通过以下两种方式解决:
- 直接使用关联属性过滤:启用你注释掉的那条语句即可,JPQL支持在WHERE子句中通过实体的关联属性进行条件判断,这种写法完全合法:
@Transactional @Modifying @Query("DELETE FROM Nickname n WHERE n.value = :value AND n.user.username = :username") void deleteNicknameByValue(@Param("username") String username, @Param("value") String value);
- 使用子查询实现关联逻辑:如果需要通过关联实体的条件过滤,也可以用子查询替代JOIN:
@Transactional @Modifying @Query("DELETE FROM Nickname n WHERE n.value = :value AND n.user.id IN (SELECT u.id FROM User u WHERE u.username = :username)") void deleteNicknameByValue(@Param("username") String username, @Param("value") String value);
注意:执行修改类操作时,@Transactional和@Modifying注解必须同时存在,以保证事务提交和实体状态更新生效。
内容的提问来源于stack exchange,提问作者milanHrabos
相关产品推荐
相关产品推荐

