【问题标题】:Delete from table on same select same table mariadb using jpa使用jpa从同一个选择同一个表mariadb的表中删除
【发布时间】:2016-07-23 05:38:52
【问题描述】:

我需要在操作同一张表时从表中删除。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 );

我收到了这个错误:

根本原因是 org.hibernate.hql.ast.QuerySyntaxException:意外 令牌:(靠近第 1 行,第 109 列 [DELETE FROM com.bcits.bfm.model.ElectricityLedgerEntity a 其中 a.elLedgerid IN ( 选择 P.elLedgerid FROM ( 选择 MAX(b.elLedgerid) FROM com.bcits.ElectricityLedgerEntity b WHERE b.accountId='24' 和 b.ledgerType='Electricity Ledger' 和 b.postType='ARREARS') P ) ] 在 org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54) 在 org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47) 在 org.hibernate.hql.ast.ErrorCounter.throwQueryException(ErrorCounter.java:82) 在 org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:284)

在 mysql 终端上运行相同的查询,但这不适用于 jpa。谁能告诉我如何使用 jpa 编写此查询。

【问题讨论】:

  • 它会告诉您问题出在哪里......该查询中的第 109 列(字符)。将其与 JPQL 规范进行比较,您就有了答案
  • 您要删除最大 ID 的ElectricityLedgerEntity 吗?
  • @ujulu 是的,我想删除具有最大 ID 的 ElectricityLedgerEntity。
  • 由于您似乎不想查看字符 109,因此它是您在 SUBQUERY 中的 FROM 子句。根据 JPA 规范,您不能将 SUBQUERY 作为 FROM 候选对象
  • 使用 JOIN 转换为多表 DELETE,而不是 IN(SELECT...)。

标签: java mysql hibernate jpa mariadb


【解决方案1】:

我不明白你为什么在最后一个括号之前使用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 stackoverflow question about it
简而言之,您不能“直接”更新/删除您在 select 子句中查询的表

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

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

【讨论】:

  • 这对我不起作用,你能告诉我如何做到这一点
  • @ anuj dhiman 我已将查询编辑为具有单个子查询。根据日志,括号可能是罪魁祸首。我认为不需要子查询。你能测试一下并告诉我错误吗?
  • updated qeury show me error : java.sql.SQLException: You can't specify target table 'LEDGER' for update in FROM 子句
【解决方案2】:

您不能在使用 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");

【讨论】:

    【解决方案3】:

    只想扩展existing answer:

    简而言之,您不能“直接”更新/删除您在 select 子句中查询的表

    这已从 MariaDB 10.3.1 开始解除:

    Same Source and Target Table

    在 MariaDB 10.3.1 之前,无法从具有相同源和目标的表中删除。从 MariaDB 10.3.1 开始,这现在是可能的。例如:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-14
      • 1970-01-01
      • 1970-01-01
      • 2014-01-15
      相关资源
      最近更新 更多