org.hibernate.HibernateException: Illegal attempt to associate a collection

 web.xml原始配置:
<!-- 过滤spring中对于hibernate的session关闭管理 -->
<filter>
   <filter-name>hibernateFilter</filter-name>
   <filter-class>
    org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
   </filter-class>
</filter>
自己写的serviceImpl.java文件中的保存更新方法(我所出现问题的位置是:多行提交的方法),在运行时总报错。如下:

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition
后来在网上狂搜解决方案,将web.xml文件改为如下:
<!-- 过滤spring中对于hibernate的session关闭管理 -->
<filter>
      <filter-name>hibernateFilter</filter-name>
         <filter-class>
             org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
         </filter-class>
      <init-param>       
         <param-name>singleSession</param-name>
        <param-value>false</param-value>    
      </init-param>
</filter>
上面的异常解决了,但又报出新的异常,如下:
org.hibernate.HibernateException: Illegal attempt to associate a collection
with two open sessions
解决这个问题的办法就是要把singleSession的值改为true
<init-param>       
         <param-name>singleSession</param-name>
        <param-value>true</param-value>   
</init-param>

我无奈了,这两个错误就好像是相互的,只能解决一个。。。
从网上搜。。还真我出现的这咱情况。。结果如下:
说明一下Open Session in View的作用,就是允许在每次的整个request的过程中使用同一个hibernate session,可以在这个request任何时期lazy loading数据。
如果是singleSession=false的话,就不会在每次的整个request的过程中使用同一个hibernate session,而是每个数据访问都会产生各自的seesion,等于没有Open Session in View。
OpenSessionInViewFilter默认是不会对session 进行flush的,并且flush mode 是 never
代码:
    protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
       Session session = SessionFactoryUtils.getSession(sessionFactory, true);
       session.setFlushMode(FlushMode.NEVER);
       return session;
    }
看getSession的方式就知道,把flush mode 设为FlushMode.NEVER,这样就算是commit的时候也不会session flush,
如果想在完成request过程中更新数据的话, 那就需要先把flush model设为FlushMode.AUTO,再在更新完数据后flush.

OpenSessionInView默认的FlushMode为
代码:

FlushMode.NEVER


可以采用在写保存更新删除代码的时候手动更改FlushMode
代码:

         this.getHibernateTemplate().execute(new HibernateCallback() {
             public Object doInHibernate(Session session) throws HibernateException {
                 session.setFlushMode(FlushMode.AUTO);
                 session.save(user);
                 session.flush();
                 return null;
             }
         });


但是这样做太繁琐了,第二种方式是采用spring的事务声明
代码:

     <bean id="baseTransaction" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
           abstract="true">
         <property name="transactionManager" ref="transactionManager"/>
         <property name="proxyTargetClass" value="true"/>
         <property name="transactionAttributes">
             <props>
                 <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
                 <prop key="save*">PROPAGATION_REQUIRED</prop>
                 <prop key="add*">PROPAGATION_REQUIRED</prop>
                 <prop key="update*">PROPAGATION_REQUIRED</prop>
                 <prop key="remove*">PROPAGATION_REQUIRED</prop>
             </props>
         </property>
     </bean>
代码:

    <bean id="userService" parent="baseTransaction">
         <property name="target">
             <bean class="com.phopesoft.security.service.impl.UserServiceImpl"/>
         </property>
     </bean>


太巧了,我们的框架就采用了这位前辈所说的第二种方案,但是为什么我把配置文件改成他说的样式还是不行呢?
郁闷中惊奇发现,不是我所有的多行提交都出问题,而只是个别的。经过一翻考虑后,确定自己写的方法体没有
问题了,那么就是方法名了,才发现,还真是方法名的问题。
原来自己写的serviceImpl.java文件的方法名要用“load”“save”“add”“update”“remove”这些词开头,这个就好像是通过这个bean-service.xml文件管理方法名一样,超出这个范围了,hibernate自身的作用就发挥不出来了。
由于自己对spring,hibernate的了解不深,暂时先这样理解。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值