JPQL查询删除不接受声明的JOIN?

时间:2018-03-13 12:59:03

标签: jpa spring-data-jpa hql jpql sql-delete

我试图理解为什么Hibernate不接受这个跟随JPQL:

@Modifying
@Query("delete from Order order JOIN order.credit credit WHERE credit.id IN ?1")
void deleteWithListaIds(List<Long> ids);

我收到的错误是:

Caused by: java.lang.IllegalArgumentException: node to traverse cannot be null!
    at org.hibernate.hql.internal.ast.util.NodeTraverser.traverseDepthFirst(NodeTraverser.java:46)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:284)

但接受这个:

@Modifying
@Query("delete from Order order WHERE order.credit.id IN ?1")
void deleteWithListaIds(List<Long> ids);

实体Order(实体Credit未映射Order s):

@Entity
public class Order {

    @Id
    @Setter
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
    @SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE, allocationSize = 1)
    @Column(name = "id", nullable = false)
    private Long id;

    @JoinColumn(name = "credit_id", foreignKey = @ForeignKey(name = "fk_order_credit"))
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    private Credit credit;


}

select语句中,接受了这两种方法,但我不明白为什么Hibernate有这种限制或者我在DELETE Jpql中做错了什么。我想在查询中声明JOIN。

我知道在更复杂的查询中解决此问题的唯一方法是创建一个子选择:

delete from Order order WHERE order.id IN (
    SELECT order.id FROM Order order
    JOIN order.credit credit
    WHERE credit.id in ?1)

这是更复杂的删除查询的正确方法吗?

我在上面的代码和Spring Boot 1.5.10.RELEASE中使用Spring Jpa Repository。

2 个答案:

答案 0 :(得分:4)

  

我不明白为什么Hibernate有这个限制。

在4.10节中的JPA Spec中指定了它:

delete_statement ::= delete_clause [where_clause]
delete_clause ::= DELETE FROM entity_name [[AS] identification_variable]

因此在删除语句中不允许加入。 为什么这样决定就是我自己的纯粹猜测。 但select_clausedelete_clause指定查询操作的内容。虽然select语句对多个实体的组合进行操作是完全正确的,但删除的连接并没有多大意义。 它只是强制您指定要删除的实体。

  

我知道在更复杂的查询中解决此问题的唯一方法是创建子选择:

     

这是更复杂的删除查询的正确方法吗?

如果你不能用更简单的方式表达它,那么是的,这就是你要走的路。

答案 1 :(得分:-1)

您可以选择使用本机SQL代替JPQL, 但这可能会带来一些不便(例如,无法进行排序)

因此要使用本机SQL,只需添加nativeQuery = true @Query(value =“ ...”,nativeQuery = true)

有关更多信息,请访问here