使用Grails v2.2.4和MySQL v5.1,我试图在一个表上使用where table的父表进行批量删除。
目前,我有一个HQL查询:
delete MemberChild mc where mc.member.id in
(select m.id from Member m where m.submissionId = :submissionId)
此查询有效,但由于两个表中的记录数量非常大,嵌套选择在我的生产系统中效率非常低。
我已尝试过这个HQL查询:
delete MemberChild mc where mc.member.submissionId = :submissionId
但这会产生生成SQL的语法错误(因为它缺少别名,所以不知道要删除的内容):
2017-07-14 11:06:39,672 [main] ERROR util.JDBCExceptionReporter - Syntax error in SQL statement "DELETE FROM MEMBER_CHILD CROSS[*] JOIN MEMBER MEMBER1_ WHERE SUBMISSION_ID=4 "; SQL statement:
delete from member_child cross join member member1_ where submission_id=4 [42000-164]
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute update query; SQL [delete from member_child cross join member member1_ where submission_id=4]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute update query
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:635)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:339)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.ExecuteUpdatePersistentMethod.doInvokeInternal(ExecuteUpdatePersistentMethod.java:62)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractStaticPersistentMethod.invoke(AbstractStaticPersistentMethod.java:72)
at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractStaticPersistentMethod.invoke(AbstractStaticPersistentMethod.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSite.invoke(PojoMetaMethodSite.java:189)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
at org.codehaus.groovy.grails.orm.hibernate.HibernateGormStaticApi.executeUpdate(HibernateGormEnhancer.groovy:605)
完成了一些直接的SQL测试和计时后,我想更改为运行以下SQL语句:
DELETE FROM MEMBER_CHILD JOIN MEMBER M ON M.ID = MEMBER_ID
WHERE M.SUBMISSION_ID = :submissionId
如果我在我的数据库上直接在sql客户端中运行此SQL语句(替换了有效的submissionId值),那么它的工作原理是:member_child记录已成功删除。
如果我尝试从我的Grails应用程序运行此SQL更新(通过SQLQuery.executeUpdate()),那么我得到以下异常:
2017-07-14 07:14:44,820 [main] ERROR util.JDBCExceptionReporter - Syntax error in SQL statement "DELETE FROM MEMBER_CHILD JOIN[*] MEMBER M ON M.ID = MEMBER_ID WHERE M.SUBMISSION_ID = ? "; SQL statement:
delete from member_child join member m on m.id = member_id where m.submission_id = ? [42000-164]
org.hibernate.exception.SQLGrammarException: could not execute native bulk manipulation query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.engine.query.NativeSQLQueryPlan.performExecuteUpdate(NativeSQLQueryPlan.java:219)
at org.hibernate.impl.SessionImpl.executeNativeUpdate(SessionImpl.java:1310)
at org.hibernate.impl.SQLQueryImpl.executeUpdate(SQLQueryImpl.java:396)
at org.hibernate.Query$executeUpdate.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
这是hibernate强加的限制吗?或者有没有办法通过这个?