HQL - 使用JOIN错误删除

Mar*_*nha 5 java mysql hibernate hql sql-delete

我试图用连接执行HQL删除..很快搜索后我发现我需要创建一个查询,就像这里建议的那样:

http://dasunhegoda.com/1093-you-cant-specify-target-table-table_name-for-update-in-from-clause/104/

这是我的查询:

    dao.executeByHql(
        "DELETE FROM FinalGradeResult e WHERE e.id IN "
        + "( SELECT id FROM "
            + "( SELECT x FROM FinalGradeResult x " 
            + "where x.student.id = :studentId "
            + " AND x.classDiscipline IN " + 
                + "(SELECT cd from ClassDiscipline cd " 
                + " where cd.clazz.id = :clazzId ) ) as X )",
    new HqlParameter("studentId", student.getId()), 
    new HqlParameter("clazzId", from.getId()));
Run Code Online (Sandbox Code Playgroud)

但我一直收到这个错误:

org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token:( near line 1, column 94 [DELETE FROM xxxxxxxxxxxx.entity.FinalGradeResult e WHERE e.id IN ( SELECT id FROM ( SELECT x FROM xxxxxxxxxxxxxxx.entity.FinalGradeResult x where x.student.id = :studentId AND x.classDiscipline IN (SELECT cd from xxxxxxxxxxxxxxxx.entity.ClassDiscipline cd where cd.clazz.id = :clazzId ) ) as X )]
Run Code Online (Sandbox Code Playgroud)

错误指出第二个(错误,"SELECT id FROM"之后的错误

编辑我试过这样和同样的错误发生:

    dao.executeByHql(
        "DELETE FROM FinalGradeResult e WHERE e.id IN "
        + "( SELECT id FROM "
        + "( SELECT x FROM FinalGradeResult x "
            + " where x.student.id = :studentId "
            + " AND x.classDiscipline.clazz.id = :clazzId )"
        + " as X )",
Run Code Online (Sandbox Code Playgroud)

编辑2:这样的查询不起作用,因为我在这个问题中发布的链接上描述的问题:

dao.executeByHql(
        "DELETE FROM FinalGradeResult  e WHERE e.id IN " + "( SELECT x.id FROM FinalGradeResult as x "
                + " where x.student.id = :studentId " + " AND x.classDiscipline.clazz.id = :clazzId )",
        new HqlParameter("studentId", student.getId()), new HqlParameter("clazzId", from.getId()));
Run Code Online (Sandbox Code Playgroud)

错误是:

Caused by: java.sql.SQLException: You can't specify target table 'tb_final_grade_result' for update in FROM clause
Run Code Online (Sandbox Code Playgroud)

在尝试了所有的东西后,我们得出结论:

  • 我们不能直接只有一个查询,因为我们无法连接DELETE.
  • 我们不能只有2个查询(一个子查询)因为我们有一个MYSQL BUG(在提供的链接上描述)
  • 我们不能有3个查询(2个子查询),因为我们在FROM子句中不能有子查询.这就是我们的第二个查询不起作用的(select * from (select ...))原因无效.

所以我决定使用NativeSQL来解决这个问题:

dao.executeBySQL(
        "   delete from tb_final_grade_result where id in "
                + " (select * from ( select finalgrade1_.id from tb_final_grade_result finalgrade1_ cross join tb_class_discipline classdisci2_ "
                + " where finalgrade1_.id_class_discipline=classdisci2_.id and finalgrade1_.id_student= :studentId and classdisci2_.id_class= :clazzId ) as tmp )",
        new HqlParameter("studentId", student.getId()), new HqlParameter("clazzId", from.getId()));
Run Code Online (Sandbox Code Playgroud)

特别感谢@scaisEdge

K.N*_*las 5

为什么需要in (select在要删除的同一表上使用?您不能只将条件放在where子句中吗?

DELETE FROM FinalGradeResult  e WHERE e.student.id = :studentId " + " AND e.classDiscipline.clazz.id = :clazzId )",
    new HqlParameter("studentId", student.getId()), new HqlParameter("clazzId", from.getId()));
Run Code Online (Sandbox Code Playgroud)

另外,我不确定参数中指的是classDiscipline.clazz.id什么?是否classDiscipline还有其他具有名为字段的clazz实体的实体?这就是查询似乎在说的。


Mar*_*nha 0

解决方案

\n\n

在尝试了一切之后,我们的结论是:

\n\n
    \n
  • 我们不能直接只有一个查询,因为我们不能在 DELETE 上进行联接。

  • \n
  • 我们不能只有 2 个查询(一个子查询),因为我们有一个 MYSQL BUG(在提供的链接中进行了描述)

  • \n
  • 我们不能有 3 个查询(2 个子查询),因为 FROM 子句中不能有子查询。这就是为什么我们的第二个查询不起作用(select * from (select ...))无效。

  • \n
\n\n

所以我决定使用NativeSQL来解决这个问题:

\n\n
dao.executeBySQL(\n        "   delete from tb_final_grade_result where id in "\n                + " (select * from ( select finalgrade1_.id from tb_final_grade_result finalgrade1_ cross join tb_class_discipline classdisci2_ "\n                + " where finalgrade1_.id_class_discipline=classdisci2_.id and finalgrade1_.id_student= :studentId and classdisci2_.id_class= :clazzId ) as tmp )",\n        new HqlParameter("studentId", student.getId()), new HqlParameter("clazzId", from.getId()));\n
Run Code Online (Sandbox Code Playgroud)\n