在 Hibernate 中批量删除时查询语法错误

Posted

技术标签:

【中文标题】在 Hibernate 中批量删除时查询语法错误【英文标题】:Query syntax error when bulk-deleting in Hibernate 【发布时间】:2010-02-22 15:59:36 【问题描述】:

我尝试使用 Hibernate HQL 查询执行批量删除,遵循 reference manunal,但我收到查询语法错误。这一行

final Query qry = getSession(false).createQuery(" delete from NewCalendarDay");

导致异常:

org.hibernate.QueryException:查询必须以 SELECT 或 FROM 开头:delete [ delete from pl.com.bms.avaro.staticData.model.NewCalendarDay ]

执行代码的类扩展了org.springframework.orm.hibernate3.support.HibernateDaoSupport,所以getSession()方法应该返回org.hibernate.Session。 我使用 spring v. 2.5.5 和 Hibernate v. 3.2.6.ga

我应该配置一些东西以能够批量删除还是什么?

编辑 Bozho 要求提供完整的堆栈跟踪,所以这里是:

org.hibernate.QueryException: query must begin with SELECT or FROM: delete [ delete from pl.com.bms.avaro.staticData.model.NewCalendarDay ]
    at org.hibernate.hql.classic.ClauseParser.token(ClauseParser.java:83)
    at org.hibernate.hql.classic.PreprocessingParser.token(PreprocessingParser.java:108)
    at org.hibernate.hql.classic.ParserHelper.parse(ParserHelper.java:28)
    at org.hibernate.hql.classic.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:216)
    at org.hibernate.hql.classic.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:185)
    at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
    at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:56)
    at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
    at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
    at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:112)
    at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1623)
    at pl.com.bms.avaro.staticData.dao.implementations.NewCalendarDayDaoImpl.deleteCalendarDaysForYear(NewCalendarDayDaoImpl.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at $Proxy43.deleteCalendarDaysForYear(Unknown Source)
    at pl.com.bms.avaro.staticData.dao.tests.TestCalendarDayDaoImpl.testFindByDateCal(TestCalendarDayDaoImpl.java:60)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at junit.framework.TestCase.runTest(TestCase.java:168)
    at junit.framework.TestCase.runBare(TestCase.java:134)
    at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:76)
    at junit.framework.TestResult$1.protect(TestResult.java:110)
    at junit.framework.TestResult.runProtected(TestResult.java:128)
    at junit.framework.TestResult.run(TestResult.java:113)
    at junit.framework.TestCase.run(TestCase.java:124)
    at junit.framework.TestSuite.runTest(TestSuite.java:232)
    at junit.framework.TestSuite.run(TestSuite.java:227)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:91)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

【问题讨论】:

您可以查看此内容以获得更好的理解 [***.com/questions/9909709/… [1]: ***.com/questions/9909709/… 【参考方案1】:

首先去掉前导空格。然后使用query.executeUpdate()执行查询

那么,即使这对您有用,我也不建议使用 HQL 删除实体。如果它们有任何关系,这些将不会级联,最终会出现不一致。

选择所有对象并在每个对象上调用session.remove(entity)。当然,如果您没有任何 x-to-x 关系,您可以继续使用 HQL,但以后添加此类时要小心。

更新:你的休眠配置中可能有这样的东西:

<prop
 key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory
</prop>

它使 Hibernate 使用经典的解析器。删除它,然后重试。

【讨论】:

删除尾随空格没有帮助。接口 org.hibernate.Session 没有定义 executeUpdate 方法,所以我不能使用它。我知道过早的优化是万恶之源,但我仍然认为加载对象只是为了删除它们是浪费资源。而且我不明白几乎从参考手册中复制的代码会以这种方式失败。 @Tadeusz Kopec 抱歉,我的意思是使用 Query 对象的 executeUpdate 方法。请给出整个堆栈跟踪。 在问题中添加了堆栈跟踪。要执行查询,我必须先创建它,但创建失败:-) 我找到了这个配置条目并将其删除 - 它有效。伟大的。现在我必须找出是谁放置了这个配置以及为什么。无论如何,至少测试有效,所以我希望它不会破坏任何其他东西。非常感谢。 @TadeuszKopec 您是否找到了之前在代码中添加的原因。删除影响任何地方?我现在也面临同样的问题【参考方案2】:

我遇到了同样的错误并评论此属性 org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory

解决问题。

【讨论】:

以上是关于在 Hibernate 中批量删除时查询语法错误的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate框架学习——批量查询(概述)

用hibernate 查询数据为修改前的数据

Hibernate 查询以 SQL 语法错误结束

在hibernate中用到的内连接查到数据怎么用

Hibernate的批量查询

SQL 中删除语法的问题 - 当子查询没有与 EXISTS 一起引入时,错误只能在选择列表中指定一个表达式