I've been having an annoying exception a lot lately, and after some research on Google and this forum I still haven't found an answer that could solve my problem.
Here's the thing - sometimes, I get the following error when trying to update or create a new object with 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)
What is really strange is that, sometimes when updating an object with the method getHibernateTemplate().saveOrUpdate(object); it will work, but sometimes with the same object and by calling the same method it doesn't work, but it seems to depend on how I get the object in the first place.
Example: let's say I have a table with 3 fields: id, type, length. What can happen is that, if I get the object by the id and update the length, then it will work. If I get it by the type and update the length, then it won't work. So what I've been doing so far to avoid the problem is to fetch the object the method that does not cause a problem later, but this is becoming more and more annoying to try and find a way that works.
Also, now I have this exception when trying to create an object (but not all of them, just on one specific table), and can't find a way for a workaround. And I tried to add @Transactional(readOnly = false) in the transaction but it didn't change anything, and displaying the mode was saying that I wasn't in read-only anyway.
Any suggestions?
Edit 26th of July: here's some configuration related to 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>
also, if it can help
<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>
Edit 31st of August:
The relevant code in my Class that extends HibernateDaoSupport, to save the objects is:
public void createObject(Object persisObj) {
getHibernateTemplate().save(persisObj);
}
I changed the single session propery from view filter. Problem solved:
<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>
That error message is typically seen when using the Spring OpenSessionInViewFilter and trying to do persistence operations outside of a Spring-managed transaction. The filter sets the session to FlushMode.NEVER/MANUAL (depending on the versions of Spring and Hibernate you're using--they're roughly equivalent). When the Spring transaction mechanism begins a transaction, it changes the flush mode to "COMMIT". After the transaction completes, it sets it back to NEVER/MANUAL, as appropriate. If you're absolutely sure that this isn't happening, then the next most likely culprit is non-thread-safe use of a Session. The Hibernate Session must be used in only one thread. If it crosses over between threads, all kinds of chaos can happen. Note that an entity loaded from Hibernate can hold a reference to the Session in which it was loaded, and handing the entity across threads can thus cause the Session to be accessed from another thread, too.
add
@Transactional
above your function
I just stumbled onto this too. I needed to change the flush mode in Spring's OpenSessionInViewFilter to manual, and suddenly I started getting this exception. I found out that the problems were hapening in methods that were not annotated as @Transactional, so I guess that Spring implicitly treats all data access code outside such methods as read only. Annotating the method solved the problem.
Another way is to call the setCheckWriteOperations method on the HibernateTemplate object.
Use below bean for HibernateTemplate in application context.
<bean id="template" class="org.springframework.orm.hibernate4.HibernateTemplate">
<property name="sessionFactory" ref="mysessionFactory"></property>
<property name="checkWriteOperations" value="false"></property>
</bean>
Try to use this
hibernateTemplate = new HibernateTemplate(sessionFactory);
hibernateTemplate.setCheckWriteOperations(false);
The error should go away as the template is not checking if you are using a transaction.
You must forgot to add @Transactional annotation to your DAO service class/method, this will specify that your database operation will be handled by spring managed transaction.
Below piece of code is worked for me.
hibernateTemplate = new HibernateTemplate(sessionFactory);
hibernateTemplate.setCheckWriteOperations(false);
1) add @Transactional above you database operation methods and 2) make sure you have annotation driven transation manager
add
above HibernateTransactionManager configuration in applicationContext.xml file
I had the same problem and after one day of investigation I observed the following declaration
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
I removed
mode="aspectj"
and the problem disappeared
来源:https://stackoverflow.com/questions/6810158/java-hibernate-write-operations-are-not-allowed-in-read-only-mode