从 ManyToMany 集合中删除成员会抛出 org.h2.jdbc.JdbcBatchUpdateException
public class Group{
@ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL, mappedBy="groups")
public Set<User> getUsers() {
if(users == null)
return new HashSet<User>();
else
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
public class User{
public void setGroups(Set<Group> groups) {
this.groups = groups;
}
@ManyToMany(cascade = CascadeType.ALL)
public Set<Group> getGroups() {
return groups;
}
}
现在,如果我删除一个用户,他应该自动从他所在的所有组中删除。无论如何,这就是我所期望的。
我得到的是这个丑陋的异常:
> Exception in thread "main"
> org.springframework.dao.DataIntegrityViolationException:
> Could not execute JDBC batch update;
> SQL [delete from USERS where ID=?];
> constraint ["FKB4DD17BD8FCA5D9E:
> PUBLIC.GROUPS_USERS FOREIGN
> KEY(USERS_ID) REFERENCES
> PUBLIC.USERS(ID)"; SQL statement:
> delete from USERS where ID=?
> [23003-143]]; nested exception is
> org.hibernate.exception.ConstraintViolationException:
> Could not execute JDBC batch update
> at
> org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:637)
> at
> org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:97)
> at
> org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:471)
> at
> org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
> at
> org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
> at
> org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
> 2010-10-31 19:41:19.044
> java[28733:903] An uncaught exception
> was raised at
> org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
> at
> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
> at
> org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
> at $Proxy22.removeUser(Unknown
> Source) at
> com.stone.gym.controller.UserController.removeUser(UserController.java:43)
> at
> com.stone.gym.view.UserView$3.handleEvent(UserView.java:121)
> at
> org.eclipse.swt.widgets.EventTable.sendEvent(Unknown
> Source) at
> org.eclipse.swt.widgets.Display.sendEvent(Unknown
> Source) at
> org.eclipse.swt.widgets.Widget.sendEvent(Unknown
> Source) at
> org.eclipse.swt.widgets.Widget.sendEvent(Unknown
> Source) at
> org.eclipse.swt.widgets.Widget.sendEvent(Unknown
> Source) at
> org.eclipse.swt.widgets.Widget.notifyListeners(Unknown
> Source) at
> org.eclipse.swt.widgets.Display.runDeferredEvents(Unknown
> Source) at
> org.eclipse.swt.widgets.Display.readAndDispatch(Unknown
> Source) at
> com.stone.gym.controller.FrontController.run(FrontController.java:30)
> at
> com.stone.gym.StoneGym.main(StoneGym.java:21)
> 2010-10-31 19:41:19.045
> java[28733:903] Java exception
> occurred Caused by:
> org.hibernate.exception.ConstraintViolationException:
> Could not execute JDBC batch update
> at
> org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
> at
> org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
> at
> org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:254)
> at
> org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
> at
> org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:172)
> at
> org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
> at
> org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
> at
> org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1001)
> at
> org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:339)
> at
> org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
> at
> org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)
> at
> org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:467)
> ... 19 more Caused by:
> org.h2.jdbc.JdbcBatchUpdateException:
> Referential integrity constraint
> violation: "FKB4DD17BD8FCA5D9E:
> PUBLIC.GROUPS_USERS FOREIGN
> KEY(USERS_ID) REFERENCES
> PUBLIC.USERS(ID)"; SQL statement:
> delete from USERS where ID=?
> [23003-143] at
> org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1101)
> at
> org.apache.commons.dbcp.DelegatingPreparedStatement.executeBatch(DelegatingPreparedStatement.java:231)
> at
> org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
> at
> org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:247)
> ... 28 more
public class Group{
@ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL, mappedBy="groups")
public Set<User> getUsers() {
if(users == null)
return new HashSet<User>();
else
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
public class User{
public void setGroups(Set<Group> groups) {
this.groups = groups;
}
@ManyToMany(cascade = CascadeType.ALL)
public Set<Group> getGroups() {
return groups;
}
}
Now if I delete a User, he should automatically be removed from all the groups he was in. That's what I expect anyway.
What I get instead is this ugly exception:
> Exception in thread "main"
> org.springframework.dao.DataIntegrityViolationException:
> Could not execute JDBC batch update;
> SQL [delete from USERS where ID=?];
> constraint ["FKB4DD17BD8FCA5D9E:
> PUBLIC.GROUPS_USERS FOREIGN
> KEY(USERS_ID) REFERENCES
> PUBLIC.USERS(ID)"; SQL statement:
> delete from USERS where ID=?
> [23003-143]]; nested exception is
> org.hibernate.exception.ConstraintViolationException:
> Could not execute JDBC batch update
> at
> org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:637)
> at
> org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:97)
> at
> org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:471)
> at
> org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
> at
> org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
> at
> org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
> 2010-10-31 19:41:19.044
> java[28733:903] An uncaught exception
> was raised at
> org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
> at
> org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
> at
> org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
> at $Proxy22.removeUser(Unknown
> Source) at
> com.stone.gym.controller.UserController.removeUser(UserController.java:43)
> at
> com.stone.gym.view.UserView$3.handleEvent(UserView.java:121)
> at
> org.eclipse.swt.widgets.EventTable.sendEvent(Unknown
> Source) at
> org.eclipse.swt.widgets.Display.sendEvent(Unknown
> Source) at
> org.eclipse.swt.widgets.Widget.sendEvent(Unknown
> Source) at
> org.eclipse.swt.widgets.Widget.sendEvent(Unknown
> Source) at
> org.eclipse.swt.widgets.Widget.sendEvent(Unknown
> Source) at
> org.eclipse.swt.widgets.Widget.notifyListeners(Unknown
> Source) at
> org.eclipse.swt.widgets.Display.runDeferredEvents(Unknown
> Source) at
> org.eclipse.swt.widgets.Display.readAndDispatch(Unknown
> Source) at
> com.stone.gym.controller.FrontController.run(FrontController.java:30)
> at
> com.stone.gym.StoneGym.main(StoneGym.java:21)
> 2010-10-31 19:41:19.045
> java[28733:903] Java exception
> occurred Caused by:
> org.hibernate.exception.ConstraintViolationException:
> Could not execute JDBC batch update
> at
> org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
> at
> org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
> at
> org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:254)
> at
> org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
> at
> org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:172)
> at
> org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
> at
> org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
> at
> org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1001)
> at
> org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:339)
> at
> org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
> at
> org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)
> at
> org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:467)
> ... 19 more Caused by:
> org.h2.jdbc.JdbcBatchUpdateException:
> Referential integrity constraint
> violation: "FKB4DD17BD8FCA5D9E:
> PUBLIC.GROUPS_USERS FOREIGN
> KEY(USERS_ID) REFERENCES
> PUBLIC.USERS(ID)"; SQL statement:
> delete from USERS where ID=?
> [23003-143] at
> org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1101)
> at
> org.apache.commons.dbcp.DelegatingPreparedStatement.executeBatch(DelegatingPreparedStatement.java:231)
> at
> org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
> at
> org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:247)
> ... 28 more
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我怀疑您在删除给定的
User
之前没有正确更新User
和Group
之间的“链接双方”,因此存在约束连接表级别的违规异常。像这样的事情:另外,我想知道为什么你要级联所有操作(你想在删除用户时删除组吗?)
I suspect that you're not updating "both sides of the link" between
User
andGroup
correctly before removing a givenUser
, hence the constraint violation exception at the join table level. Something like that:Also, I wonder why you're cascading ALL operations (do you want to remove groups when removing a user?)
您需要将 Group 的 inverse 设置为 true 并删除用户将删除相对关系。但是,如果你的User级联全部了,Group也会被删除。因此将其更改为保存更新。
Pascal的建议是一个更好的方法。明确删除关系始终是首选。
You need to set Group's inverse to true and delete a user will remove the relative relation. However, if you User's cascade is all, Group will be removed too. So change it to save-update.
Pascal's suggestion is a better way. Delete the relation explicitly is always preferred.
您可以使用 Hibernate 站点 (http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#entity-mapping-association)。确保从 Group 实体中的 @ManyToMany 中删除 mappedBy。
You can use this technic, described at Hibernate site (http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#entity-mapping-association). Make sure to remove mappedBy from @ManyToMany in Group entity.