在 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 中批量删除时查询语法错误的主要内容,如果未能解决你的问题,请参考以下文章