器件分类删除代码走读

问题

日前小何在器件管理2模块中删除一个器件分类(同时删除器件分类审批团队)时,系统抛出异常;表现为,审批团队成功删除了,器件分类删除不成功。

  1. 为了描述清楚该问题,我们先描述器件分类与审批团队的关系(hibernate映射关系):
    Hibernate映射关系
    审批团队--many-to-one-->器件分类
    器件分类--one-to-one-->审批团队
    
  2. 删除器件分类的manager代码块:
    com.kedacom.ksoa3.apparatus2.domain.manager.ApparatusTypeManagerImpl.removeApparatusType
    	ApparatusTypePO type = typeDao.getById(typeId);
    	ApparatusTypeTeamPO team = type.getApparatusTypeTeam();
    	if (team != null) {
    		teamDao.remove(team);
    	}
    
    	if (!this.removeApparatusChildrenType(typeId)) {
    		return Message.getMessage(false, "无法删除,请联系管理员!");
    	}
     
  3. 删除时发生异常的信息
    2009-09-11 11:11:58 [ERROR]  Duplicate key or integrity constraint violation message from server: "Cannot delete or update a parent row: a foreign key constraint fails (`ksoa3/apparatus2_type_team`, CONSTRAINT `FK78347D72721385C6` FOREIGN KEY (`type_id`) REFERENCES `apparatus2_type` (`id`))"
    
     <org.hibernate.util.JDBCExceptionReporter> 
    org.hibernate.exception.ConstraintViolationException: could not execute update query
    	at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
    	at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
    	at org.hibernate.hql.ast.exec.BasicExecutor.execute(BasicExecutor.java:84)
    	at org.hibernate.hql.ast.QueryTranslatorImpl.executeUpdate(QueryTranslatorImpl.java:396)
    	at org.hibernate.engine.query.HQLQueryPlan.performExecuteUpdate(HQLQueryPlan.java:259)
    	at org.hibernate.impl.SessionImpl.executeUpdate(SessionImpl.java:1141)
    	at org.hibernate.impl.QueryImpl.executeUpdate(QueryImpl.java:94)
    	at com.kedacom.common.base.domain.dao.BaseDaoHibernateImpl$1.doInHibernate(BaseDaoHibernateImpl.java:271)
    	at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:419)
    	at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:339)
    	at com.kedacom.common.base.domain.dao.BaseDaoHibernateImpl.executeHql(BaseDaoHibernateImpl.java:264)
    	at com.kedacom.components.tree.manager.impl.TreeNodeManagerImpl.removeTreeNodeAndDescendants(TreeNodeManagerImpl.java:623)
    	at com.kedacom.components.tree.manager.impl.TreeNodeManagerImpl.removeLeaf(TreeNodeManagerImpl.java:596)
    	at com.kedacom.ksoa3.apparatus2.domain.manager.ApparatusTypeManagerImpl.removeApparatusChildrenType(ApparatusTypeManagerImpl.java:103)
    	at com.kedacom.ksoa3.apparatus2.domain.manager.ApparatusTypeManagerImpl.removeApparatusType(ApparatusTypeManagerImpl.java:216)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:585)
    	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
    	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.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    	at $Proxy73.removeApparatusType(Unknown Source)
    	at com.kedacom.ksoa3.apparatus2.web.controller.ApparatusTypeController.delete(ApparatusTypeController.java:118)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:585)
    	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:421)
    	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:136)
    	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:326)
    	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:313)
    	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
    	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
    	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    	at com.automatedlogic.domino.sso.DominoLoginFilter.doFilter(DominoLoginFilter.java:87)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
    	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    	at java.lang.Thread
    
    .run(Thread
    
    .java:595)
    Caused by: java.sql.SQLException: Duplicate key or integrity constraint violation message from server: "Cannot delete or update a parent row: a foreign key constraint fails (`ksoa3/apparatus2_type_team`, CONSTRAINT `FK78347D72721385C6` FOREIGN KEY (`type_id`) REFERENCES `apparatus2_type` (`id`))"
    
    
    	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2001)
    	at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1168)
    	at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1279)
    	at com.mysql.jdbc.Connection.execSQL(Connection.java:2281)
    	at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1825)
    	at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1667)
    	at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:102)
    	at org.hibernate.hql.ast.exec.BasicExecutor.execute(BasicExecutor.java:75)
    	... 57 more
    
  4. 异常发生时的SQL信息
    // 这里省略与tree_node、tree的关联
    
    
    select type.*, team.* from apparatus2_type type left outer
    
     join apparatus2_type_team team on team.type_id=type.id where type.id=?
    
    select team.* from apparatus2_type_team team where team.type_id=?
    
    delete from apparatus2_type where tree_id='3' and left_node>=2 and right_node<=3
    2009-09-11 11:11:58 [WARN]  SQL Error: 1451, SQLState: 23000 <org.hibernate.util.JDBCExceptionReporter>
    2009-09-11 11:11:58 [ERROR]  Duplicate key or integrity constraint violation message from server: "Cannot delete or update a parent row: a foreign key constraint fails (`ksoa3/apparatus2_type_team`, CONSTRAINT `FK78347D72721385C6` FOREIGN KEY (`type_id`) REFERENCES `apparatus2_type` (`id`))"
    
     <org.hibernate.util.JDBCExceptionReporter> 
    org.hibernate.exception.ConstraintViolationException: could not execute update query
    ...
    
    delete from apparatus2_type_team where id=?
    

分析与调试

  1. 整个过程是否在Spring事务控制下?
    1. 经查,整个方法是在Spring事务控制下的。
  2. 打开Hibernate SQL打印
    1. 发现了上面列出的"异常发生时的SQL信息",其中删除team和删除type的顺序恰好与我们指定的相反。为什么会这样呢?我们在最后给出答案。
  3. 尝试使用Hibernate的级联删除,在删除type的同时级联删除team
    1. 没有效果,因为我们是采用sql语句删除type的,这个sql语句不会引发级联删除的;只有对对象的操作,才可能引发对其属性的级联操作。
  4. hibernate改变了SQL执行的顺序,是否为inverse问题?
    1. (后 来发现也不是inverse的问题,而是hiberanate清理缓存的机制引起的)根据这个猜测,我们认为只要在删除team时手工清理一下 session,hibernate就不会改变SQL执行的顺序。于是,我们就改变了 ApparatusTypeTeamDaoHibernateImpl删除team的行为(更改代码后,问题解决):
      com.kedacom.ksoa3.apparatus2.domain.dao.ApparatusTypeTeamDaoHibernateImpl.remove
      	public boolean remove(ApparatusTypeTeamPO team){
      		super.remove(team);
      		super.getHibernateTemplate().flush();
      		return true;
      	} 

最后说明为什么Hibernate会改变我们sql的执行顺序——Hibernate Session清理时,执行sql的顺序:

Hibernate Session在清理缓存时,会按照什么顺序来执行Sql语句?

http://www.wangchao.net.cn/bbsdetail_854253.html

  1. 按照应用程序调用Session.Save()方法的先后顺序,执行所有对实体进行插入的insert语句。
  2. 执行所有对实体进行更新的update语句。
  3. 执行所有对集合进行删除的delete语句。
  4. 执行所有对集合元素进行更新、删除、插入的sql语句。
  5. 执行所有对集合进行插入的insert语句。
  6. 按照应用程序调用Sesson.delete()方法的先后顺序,执行所有对实体进行删除的delete语句。

根据上面的说明,在我们的代码里首先由两个get生成两条select语句;
然后我们的代码delete一个team对象;
再执行一个delete type的sql语句(我们的removeApparatusChildrenType实际上是通过sql语句来删除type对象的);

由于type同时也是team的一个属性,所以会依据第4条"执行所有对集合元素进行更新、删除、插入的sql语句"先执行delete type的sql语句,然后才会根据第6条"按照应用程序调用Sesson.delete()方法的先后顺序,执行所有对实体进行删除的delete语 句"来执行delete team对象的语句。

weixin073智慧旅游平台开发微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码
python017基于Python贫困生资助管理系统带vue前后端分离毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码
weixin102旅游社交微信小程序+ssm后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值