Java/Hibernate - 在只读模式下不允许写操作

Gui*_*ume 15 java spring hibernate readonly

我最近经常遇到一个烦人的例外,经过对谷歌和这个论坛的一些研究后,我仍然没有找到可以解决我的问题的答案.

这是事情 - 有时,我尝试使用hibernate更新或创建一个新对象时出现以下错误:

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
at org.springframework.orm.hibernate3.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1186)
at org.springframework.orm.hibernate3.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:696)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:419)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.save(HibernateTemplate.java:694)
Run Code Online (Sandbox Code Playgroud)

真正奇怪的是,有时用方法更新对象时getHibernateTemplate().saveOrUpdate(object);它会起作用,但有时候使用相同的对象并通过调用相同的方法它不起作用,但它似乎取决于我如何获得对象第一名.

示例:假设我有一个包含3个字段的表:id,type,length.可能发生的是,如果我通过id获取对象并更新长度,那么它将起作用.如果我按类型获取并更新长度,那么它将无法工作.所以到目前为止我一直在做的是避免这个问题,就是获取对象后面不会引起问题的方法,但是尝试找到一种有效的方法会变得越来越烦人.

此外,现在我在尝试创建一个对象(但不是所有对象,仅在一个特定的表上)时遇到此异常,并且无法找到解决方法的方法.我试图@Transactional(readOnly = false)在事务中添加但它没有改变任何东西,显示模式就是说我不是只读的.

有什么建议?

编辑7月26日:这里有一些与hibernate相关的配置

<property name="hibernateProperties">
    <props>
        <prop key="jdbc.fetch_size">20</prop>
        <prop key="jdbc.batch_size">25</prop>
        <prop key="cglib.use_reflection_optimizer">true</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        <prop key="connection.autoReconnect">true</prop>
        <prop key="connection.autoReconnectForPools">true</prop>
        <prop key="connection.is-connection-validation-required">true</prop>
    </props>
</property>
Run Code Online (Sandbox Code Playgroud)

如果它可以帮助

<property name="transactionAttributes">
    <props>
        <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
        <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
        <prop key="execute*">PROPAGATION_REQUIRED</prop>
        <prop key="add*">PROPAGATION_REQUIRED</prop>
        <prop key="create*">PROPAGATION_REQUIRED</prop>
        <prop key="update*">PROPAGATION_REQUIRED</prop>
        <prop key="delete*">PROPAGATION_REQUIRED</prop>
    </props>
</property>
Run Code Online (Sandbox Code Playgroud)

编辑8月31日:HibernateDaoSupport为了保存对象,我的类中扩展的相关代码是:

public void createObject(Object persisObj) {
    getHibernateTemplate().save(persisObj);
}
Run Code Online (Sandbox Code Playgroud)

Rya*_*art 13

当使用Spring OpenSessionInViewFilter并尝试在Spring管理的事务之外执行持久性操作时,通常会看到该错误消息.过滤器将会话设置为FlushMode.NEVER/MANUAL(取决于您使用的Spring和Hibernate的版本 - 它们大致相当).当Spring事务机制开始一个事务时,它将刷新模式更改为"COMMIT".事务完成后,它会根据需要将其设置为NEVER/MANUAL.如果您完全确定没有发生这种情况,那么下一个最可能的罪魁祸首就是非线程安全地使用Session.Hibernate Session必须只在一个线程中使用.如果它穿过线程之间,就会发生各种混乱.请注意,从Hibernate加载的实体可以保存对加载它的Session的引用,因此跨线程处理实体也可以导致从另一个线程访问Session.

  • 最好的开始方法可能是在InvalidDataAccessApiUsageException上添加一个异常断点,然后调试应用程序并使它实现。然后检查堆栈以了解如何处理该异常。尤其要检查打开会话的方式和位置以及是否启动了事务。您可以从异常堆栈跟踪中了解其中的一些内容,但最好将其保存在调试器中。 (2认同)

Fır*_*ÇÜK 7

我从视图过滤器更改了单个会话属性.问题解决了:

  <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>
Run Code Online (Sandbox Code Playgroud)

  • 我试过`getHibernateTemplate().getSessionFactory().getCurrentSession().setFlushMode(FlushMode.AUTO);`,我的问题解决了...... (3认同)

Ahm*_*emi 7

@Transactional
Run Code Online (Sandbox Code Playgroud)

在你的功能之上


alh*_*001 6

我也偶然发现了这一点.我需要将Spring的OpenSessionInViewFilter中的刷新模式更改为手动,突然我开始得到这个异常.我发现问题是在没有注释为@Transactional的方法中出现问题,所以我猜Spring会隐式地将所有数据访问代码视为只读方法.注释该方法解决了这个问题.

另一种方法是在HibernateTemplate对象上调用setCheckWriteOperations方法.


小智 5

应用程序上下文中使用bean下面的HibernateTemplate.

<bean id="template" class="org.springframework.orm.hibernate4.HibernateTemplate">  
        <property name="sessionFactory" ref="mysessionFactory"></property>
        <property name="checkWriteOperations" value="false"></property>
        </bean>
Run Code Online (Sandbox Code Playgroud)