Write operations are not allowed in read-only mode - Issue while persisting

11,918

You are missing TransactionManager definition, see http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/transaction.html

[UPDATE] Previously i was writing from my mobile so it was hard to provide details, here is what you need to do:

  1. Spring xml config:

    <tx:annotation-driven/>
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 
    
  2. Add @Transactional annotation to CustomerDaoImpl.insertCustomer method

Now your code should work.

Please note that @Transactional annotation should be used in service layer, not in DAO layer like in this example.
@Transactional annotation tells spring to create proxy which "wraps" annotated method with transaction using aspects.

Share:
11,918
Srivatsa N
Author by

Srivatsa N

A lazy programmer who wants to write every piece of code right !!!

Updated on June 11, 2022

Comments

  • Srivatsa N
    Srivatsa N almost 2 years

    I have been facing the below error while trying to save the object to database. I tried the solution mentioned here1 and here2 but no good. I was following a tutorial but the only difference is versions of Spring and Hibernate.

    I am able to persist the object directly using the SessionFactory but it fails with below error if I try this with HibernateDaoSupport

    spring.xml

    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
        <property name="username" value="system" />
        <property name="password" value="xxx" />
    </bean>
    
    <context:annotation-config/>
    
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="packagesToScan" value="org.sri.sphiber.model"></property>
        <property name="hibernateProperties">
            <props>
                <prop key="dialect">org.hibernate.dialect.OracleDialect</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>
    
    
    
    <bean id="customerDAOImpl" class="org.sri.sphiber.dao.CustomerDAOImpl">
        <property name="hibernateTemplate" ref="hibernateTemplate" />
    </bean>
    
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    
    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
        <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 
    

    CustomerDAOImpl.java

    public class CustomerDAOImpl extends HibernateDaoSupport {
    
        public boolean insertCustomer(Customer cust){
    
            try {
                getHibernateTemplate().saveOrUpdate(cust);
            } catch (DataAccessException e) {
                e.printStackTrace();
                return false;
            }
            return true;
        }
    
    }
    

    Invoke it using.

    public class MainClass {
    
        public static void main(String[] args) {
    
    
                ApplicationContext appContext = new ClassPathXmlApplicationContext("spring.xml");
                CustomerDAOImpl hdi=appContext.getBean("customerDAOImpl",CustomerDAOImpl.class);
    
    
                Customer customer=new Customer();
                customer.setCustomerName("Sri");
    
                boolean isUpdated = hdi.insertCustomer(customer);
    
        }
    
    
    }
    

    Error message.

    Aug 10, 2014 12:45:52 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
    INFO: HHH000232: Schema update complete
    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.
        at org.springframework.orm.hibernate4.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1135)
        at org.springframework.orm.hibernate4.HibernateTemplate$16.doInHibernate(HibernateTemplate.java:684)
        at org.springframework.orm.hibernate4.HibernateTemplate.doExecute(HibernateTemplate.java:340)
        at org.springframework.orm.hibernate4.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:308)
        at org.springframework.orm.hibernate4.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:681)
        at org.sri.sphiber.dao.CustomerDAOImpl.insertCustomer(CustomerDAOImpl.java:16)
        at org.sri.sphiber.main.MainClass.main(MainClass.java:26)
    

    Version Details :

    Spring version : spring-framework-4.0.6.RELEASE
    Hibernate Version : hibernate-release-4.3.5.Final
    Database : Orcale 11g
    
  • Srivatsa N
    Srivatsa N over 9 years
    I added the TransactionManager as suggested by you (edited the question) , but still got the same error, I dint quite follow that. Can you please explain a bit more on this ? Thanks.
  • Srivatsa N
    Srivatsa N over 9 years
    It just worked like charm, it was looking for a bean named transactionManager instead of txManager. Let me take a look at the docs again. I guess I miss understood the way it works. :) Thanks a lot
  • Philipp Wirth
    Philipp Wirth over 7 years
    If you configure your spring application programmatically you can add @ EnableTransactionManagement annotation which is the equivalent for <tx:annotation-driven/>. So just add @EnableTransactionManagement annotation to your @ Configuration annotated class.