Операции записи не разрешены в режиме только для чтения — проблема при сохранении

Я столкнулся с приведенной ниже ошибкой при попытке сохранить объект в базе данных. Я попробовал решение, упомянутое здесь1 и здесь2, но бесполезно. Я следовал руководству, но единственная разница версии Spring и Hibernate.

Я могу сохранить объект напрямую, используя SessionFactory, но он не работает с ошибкой ниже, если я попытаюсь это сделать с помощью 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> 

КлиентDAOImpl.java

public class CustomerDAOImpl extends HibernateDaoSupport {

    public boolean insertCustomer(Customer cust){

        try {
            getHibernateTemplate().saveOrUpdate(cust);
        } catch (DataAccessException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

}

Вызовите его с помощью.

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);

    }


}

Сообщение об ошибке.

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)

Сведения о версии:

Spring version : spring-framework-4.0.6.RELEASE
Hibernate Version : hibernate-release-4.3.5.Final
Database : Orcale 11g

person Srivatsa N    schedule 09.08.2014    source источник


Ответы (2)


У вас отсутствует определение TransactionManager, см. http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/transaction.html

[ОБНОВЛЕНИЕ] Раньше я писал со своего мобильного телефона, поэтому было сложно предоставить подробности, вот что вам нужно сделать:

  1. XML-конфигурация Spring:

    <tx:annotation-driven/>
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 
    
  2. Добавьте аннотацию @Transactional к методу CustomerDaoImpl.insertCustomer.

Теперь ваш код должен работать.

Обратите внимание, что аннотацию @Transactional следует использовать на уровне службы, а не на уровне DAO, как в этом примере.
Аннотация @Transactional указывает Spring создать прокси, который «обертывает» аннотированный метод транзакцией с использованием аспектов.

person rgrebski    schedule 09.08.2014
comment
Я добавил TransactionManager, как вы предложили (отредактировал вопрос), но все равно получил ту же ошибку, я не совсем следую этому. Не могли бы вы объяснить немного больше об этом? Спасибо. - person Srivatsa N; 10.08.2014
comment
Он просто работал как шарм, он искал bean-компонент с именем transactionManager вместо txManager. Позвольте мне еще раз взглянуть на документы. Наверное, я не понял, как это работает. :) Большое спасибо - person Srivatsa N; 10.08.2014
comment
Если вы настраиваете приложение Spring программно, вы можете добавить аннотацию @ EnableTransactionManagement, которая эквивалентна ‹tx:annotation-driven/›. Поэтому просто добавьте аннотацию @EnableTransactionManagement в свой аннотированный класс @ Configuration. - person Philipp Wirth; 28.08.2016

В файле конфигурации

сделать изменение: -

@Configuration
@EnableTransactionManagement   <-----Put this line
public PersistenceConfig{
//your code
}

(OR)

@Bean
@Autowired
public HibernateTemplate getHibernateTemplate(SessionFactory session) {
        HibernateTemplate hb = new HibernateTemplate();
        hb.setCheckWriteOperations(false);
        hb.setSessionFactory(session);
        return hb;
    }
person SAN    schedule 20.08.2017