使用 jpa 从 table 相同 select 相同 table mariadb 中删除

Delete from table on same select same table mariadb using jpa

我需要从 table 中删除相同 table 的操作。JPA 查询是

DELETE  FROM com.model.ElectricityLedgerEntity a 
Where a.elLedgerid IN 
 (SELECT P.elLedgerid FROM
   (SELECT MAX(b.elLedgerid) 
    FROM com.model.ElectricityLedgerEntity b
    WHERE b.accountId='24' and b.ledgerType='Electricity Ledger' and b.postType='ARREARS') P );

我收到这个错误:

with root cause org.hibernate.hql.ast.QuerySyntaxException: unexpected token: ( near line 1, column 109 [DELETE FROM com.bcits.bfm.model.ElectricityLedgerEntity a Where a.elLedgerid IN ( SELECT P.elLedgerid FROM ( SELECT MAX(b.elLedgerid) FROM com.bcits.ElectricityLedgerEntity b WHERE b.accountId='24' and b.ledgerType='Electricity Ledger' and b.postType='ARREARS') P ) ] at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54) at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47) at org.hibernate.hql.ast.ErrorCounter.throwQueryException(ErrorCounter.java:82) at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:284)

相同的查询是 运行 在 mysql 终端上,但这不适用于 jpa。任何人都可以告诉我如何使用 jpa 编写此查询。

我不明白为什么要在最后一个括号之前使用 P...

下面的代码还不够吗?

DELETE  FROM com.model.ElectricityLedgerEntity a 
Where a.elLedgerid IN    
  (SELECT MAX(b.elLedgerid) 
   FROM com.model.ElectricityLedgerEntity b
   WHERE b.accountId='24' and b.ledgerType='Electricity Ledger' and
   b.postType='ARREARS')    

绕过 mysql 子查询限制的编辑:

新错误java.sql.SQLException: You can't specify target table 'LEDGER' for update in FROM clause 当您将它与 JPA 一起使用时,它在 mysql 中是已知的。这是一个 MySQL 限制。 A recent Whosebug question about it
简而言之,您不能 "directly" updated/deleted 您在 select 子句

中查询的 table

现在我明白了为什么您的原始查询执行了看似不必要的多个子查询(虽然它对 mysql 很有用)并且具有 "special" 语法。 我不知道在 JPA 中解决这个问题的技巧(我现在很长时间不使用 MySQL DBMS)。

在你那里,我会做两个查询。第一个你 select 预期的最大 elLedgerid 和第二个你可以删除具有在上一个查询中检索到的 id 的行。 如果您的 sql 模型设计良好,sql 索引放置得当并且访问数据库的时间正确,那么您应该不会有性能问题。

您不能在使用 Hibernate 的单个查询中执行此操作。如果你想用 Hibernate 删除最大行数,你必须分两步完成。首先,您可以找到最大条目,然后可以在 WHERE 子句中使用该值进行删除。

但是您编写的查询 应该 实际上 运行 作为原始 MySQL 查询。那么,为什么不尝试将该查询作为原始查询来执行呢:

String sql = "DELETE FROM com.model.ElectricityLedgerEntity a " +
             "WHERE a.elLedgerid IN (SELECT P.elLedgerid FROM " +
             "(SELECT MAX(b.elLedgerid) FROM com.model.ElectricityLedgerEntity b " + 
             "WHERE b.accountId = :account_id AND b.ledgerType = :ledger_type AND " +
             " b.postType = :post_type) P );";
Query query = session.createSQLQuery(sql);
query.setParameter("account_id", "24");
query.setParameter("ledger_type", "Electricity Ledger");
query.setParameter("post_type", "ARREARS");

只想扩展 :

In brief, you cannot "directly" updated/deleted a table that you query in a select clause

这是从 MariaDB 10.3.1 开始解除的:

Same Source and Target Table

Until MariaDB 10.3.1, deleting from a table with the same source and target was not possible. From MariaDB 10.3.1, this is now possible. For example:

DELETE FROM t1 WHERE c1 IN (SELECT b.c1 FROM t1 b WHERE b.c2=0);