Hibernate无效数据访问API使用异常 - 只读模式

6

摘要:异常告诉我事务是只读的; 调试println似乎表明我不在只读模式下。

对于互联网出版编辑的类-如果我打错了什么,对不起,但这就是让我困扰的代码要点。当调用其他对象类型时,saveOrUpdate可以正常工作,但在这种情况下无法正常工作。 我在调试时添加了println到saveOrUpdate。 我没有编写抽象类,我只是尝试使用它(现在正在调试它)。

相关输出如下所示。 不确定接下来该怎么做。

调查后更新: 我还在进行一些spring配置的更新,一个同事指出,我从一个方法中调用的updateAParameter以一种方式使用spring,而损坏的方法则以另一种方式使用spring。不幸的是,我想去修复的那种方式。

因此,我现在理解的问题是,如果我手动实例化DataObjectDAOImpl,请通过获取bean在方法中,然后允许我正确地将数据写回Hibernate。 如果我使用spring为该bean设置类变量,以便我不必在每个方法中实例化它,那么即使它报告不在只读模式下,但在访问尝试写入Hibernate的方法时,也会发生InvalidDataAccessApiUsageException。我的同事对这个问题有一个理论,但我不明白他在说什么-关于从SampleClass中提取接口的一些内容。

// Old way that works.
public class SampleClass {
public void someMethod {
ApplicationContext ac = ApplicationContextFactory.getApplicationContext();
DataObjectDAOImpl dodi = ((DataObjectDAOImpl) ac.getBean("dodi"));
//this works
dodi.updateAParameter("foo", exampleDataObject);
}
}

//New way that doesn't work but I would like it to.
public class SampleClass {
private DataObjectDAOImpl dodi = null;
//'dodi' has getter and setter methods that I am not pasting here for simplicity
public void someMethod {    
//causes Exception
dodi.updateAParameter("foo", exampleDataObject);
}
}

这是来自Spring配置的相关Bean:

<bean id="sampleclass" class="com.service.SampleClass" scope="prototype">
    <property name="dodi" ref="doDAOimpl"/>
</bean>

这里是DAOImpl,对于旧的和新的方式都是相同的。

public class DataObjectDAOImpl extends AbstractSpringDaoStuff {

 ...

 public void updateAParameter(String parameter, DataObject do) {
  do.setAParameter(parameter);
  super.saveOrUpdate(do);
 }

}


public abstract class AbstractSpringDaoStuff extends HibernateDaoSupport {

   ...

    @Transactional(readOnly=false)
     protected void saveOrUpdate(Object obj) {
     System.out.println ( "Read-only?: " + TransactionSynchronizationManager.isCurrentTransactionReadOnly () );

         getHibernateTemplate().saveOrUpdate(obj);
     }        
}

应用服务器的输出:

     [java] Read-only?: false
     [java] - Method execution failed:
     [java] 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.
     [java]     at org.springframework.orm.hibernate3.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1186)
     [java]     at org.springframework.orm.hibernate3.HibernateTemplate$16.doInHibernate(HibernateTemplate.java:750)
     [java]     at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:419)
     [java]     at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
     [java]     at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:748)
     [java]     at com.est.dao.AbstractSpringDaoStuff.saveOrUpdate(AbstractSpringDaoMDA.java:24)
etc

我改变了单个会话属性。问题解决了。 - Fırat Küçük
getHibernateTemplate().getSessionFactory().getCurrentSession().setFlushMode(FlushMode.AUTO); - prem30488
1个回答

3
我所能看到的一个可能的问题是,您正在从同一Bean调用@Transactional方法。我不确定它如何与您的异常相关,但由于Spring的声明性事务管理是通过基于代理的AOP实现的,这意味着该注释无效。
另请参阅:
- 《7.6.1 理解AOP代理》 - 《10.5.1 理解Spring框架的声明式事务实现

谢谢。我遇到了同样的错误。我在我的方法中添加了 @Transactional(readOnly = false),现在它可以工作了。 - Ron Romero
这对我非常有帮助,尽管你发布回复已经将近2.5年了。非常感谢你,@axtavt。 - Sid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接