记录一次排查问题:Hibernate删除数据表报InvalidDataAccessApiUsageException

现象

通过service层调用dao层方法,通过hibernate删除用户管理表TB_SYSACCOUNT条目的时候报错:

org.springframework.dao.InvalidDataAccessApiUsageException: 
Write operations are not allowed in read-only mode (FlushMode.MANUAL): 
Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.

分析

hibenate映射配置检查

首先怀疑是不是hibernate配置有问题,查看applicationContext.xml中hibernate的配置

 <property name="mappingDirectoryLocations">
     <list>
       <value>classpath:/com/corsair/rbac/entity</value> //SysAccount类所在路径
       <value>classpath:/com/corsair/base/entity</value>
       <value>classpath:/com/corsair/info/entity</value>
        <value>classpath:/com/corsair/location/entity</value>
        <value>classpath:/com/corsair/eventsrv/entity</value>
      </list>
  </property>

对比要删除的条目的实体类SysAccount,路径相符,排除hibernate映射问题。
在这里插入图片描述

Spring AOP配置检查

考虑到Service层中调用Dao层方法执行删除操作,切面可能配置不正确,查看AOP配置

   <!-- 定义切面,在 com.*.service.*Service.*(..) 中执行有关的hibernate session的事务操作 -->
 <aop:config>
        <aop:pointcut id="accountOperation" expression="execution(* com.corsair.rbac.service.*Service.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="accountOperation"/>
   </aop:config>

检查execution(* com.corsair.rbac.service.*Service.*(..))

  • 第一个 * 表示方法返回值类型可以为任意类型
  • 第二个 * 表示cn.jkstudio包下面的任意包
  • 第三个 * 表示service包下面的任意包
  • 第四个 * 表示service.任意包 下面的任意一个类
  • 第五个 * 表示service.任意包.任意类下面的任意一个方法

查看Service文件路径也没有问题,排除Spring AOP配置问题
在这里插入图片描述

hibernate表结构检查

百思不得其解中,手动输入SQL试验能否删除,发现还是不可以,这时候已经接近真相了,SQL直接删除不行,Java执行操作当然也不可以。经过排查发现违反了唯一安全性约束,也就是说SysAccount这张表有键在其它表中被引用。

最后检查SysAccount.hbm.xml,发现要删除的TB_SYSACCOUNT表中有1个字段在TB_SYSACCOUNTROLE表中被引用,增加级联删除cascade="delete

   <set name="sysAccountRoles" inverse="true" lazy="false" cascade="delete">
            <key>
                <column name="ACCOUNT_ID">
                    <comment>用户id</comment>
                </column>
            </key>
            <one-to-many class="com.corsair.rbac.entity.SysAccountRole"/>
        </set>

重新启动程序测试,顺利通过。

感谢

参考了以下大神的文章最终解决,在此表示感谢,程序员路漫漫其修远兮,吾将上下而求索。
https://blog.csdn.net/jilijelon/article/details/71305636
https://blog.csdn.net/xc121566/article/details/84931992
https://blog.csdn.net/wj123446/article/details/77873661
https://blog.csdn.net/qq_34902590/article/details/75315061

猜你喜欢

转载自blog.csdn.net/qq_34307801/article/details/104264122