Почему DataSourceTransactionManage не выполняет откат, в то время как HibernateTransactionManager делает?

1
<bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        lazy-init="true">
        <property name="dataSource" ref="dataSource" />
    </bean>

При создании приложения с использованием весны и спящего режима, если я использую DataSourceTransactionManager, то при исключении он не откатывается. Похоже, он использует auto-comit в разных сеансах. Однако, если я изменю диспетчер транзакций на org.springframework.orm.hibernate3.HibernateTransactionManager, откат будет работать, как ожидалось. Или это, если мы используем hibernate, тогда нам нужно использовать HibernateTransactionManager?

Nb: Мой сервис аннотируется с @Transactional(rollbackFor = { Throwable.class} )

  • 0
    Что является базовой базой данных?
Теги:
spring
hibernate

2 ответа

2
Лучший ответ

При работе с простым спящем режиме для управления транзакциями необходимо следующее:

Session s = sessionfactory.openSession();
Transaction tx = null;
try {
tx = s.beginTransaction();
// Your data manipulation here
tx.commit();
} catch (Exception e) {
if (tx != null) { tx.rollback();}
} finally {
s.close();
}

Это также делает HibernateTransactionManager (при необходимости открывать сеанс, начинать транзакцию, впоследствии совершать/откатывать).

Теперь то, что вы пытаетесь сделать, - это следующее (которое является похожим на DataSourceTransactionManager, который работает на "DataSource, а не на сеансе").

Session s = sessionfactory.openSession();
Connection conn = null;
try {
    conn = s.connection();
    // Your data manipulation here
    conn.commit();
} catch (Exception e) {
    if (conn != null) { 
        try {
            conn.rollback();
        catch (IOExceptin) {}
    }
} finally {
    s.close();
}

Что не будет работать, поскольку фактическая транзакционная единица, сеанс, никогда не получает информацию о фиксации или откате. Поэтому в худшем случае, в зависимости от вашего флеш-режима, все (или частично) становится совершенным.

Короче всегда используйте диспетчер транзакций, который соответствует вашей технологии.

При использовании простой спящего режима используйте HibernateTransactionManager, при использовании JPA используйте JpaTransactionManager, не используйте DataSourceTransactionManager в тех случаях, поскольку это можно использовать только в ситуациях, когда используется только обычный JDBC.

DataSourceTransactionManager четко заявляет, что он работает с DataSource и базовым соединением. В то время как, когда один использует Hibernate транзакции управляются с помощью спящей Session, это уровня, на котором HibernateTransactionManager работает на. Для JPA это EntityManager и это то, что распознает JpaTransactionManager.

  • 0
    Можете ли вы опубликовать ссылку, которая говорит, что DataSourceTransactionManager предназначен только для простого JDBC.
  • 0
    Там нет (Javadocs делают некоторые намеки в этом направлении), но это просто так, как есть. DataSourceTransactionManager ничего не знает о session гибернации и никогда не вызовет сброс или фиксацию на нем. Следовательно, ничего не произойдет. Он будет вызывать commit для соединения, но поскольку sql не был выдан, ничего не будет зафиксировано (если вы не вызываете flush для всех ваших методов DAOs).
Показать ещё 2 комментария
0

Согласно весенней документации:

Реализации PlatformTransactionManager обычно требуют знания среды, в которой они работают: JDBC, JTA, Hibernate и т.д.

Если вы используете JTA в контейнере Java EE, вы используете контейнер DataSource, полученный через JNDI, совместно с Sprinter JtaTransactionManager.

Вы также можете легко использовать локальные транзакции Hibernate...

В этом случае вам нужно определить Hibernate LocalSessionFactoryBean, который ваш код приложения будет использовать для получения экземпляров сеанса Hibernate... в этом случае относится к типу HibernateTransactionManager.

Точно так же, как DataSourceTransactionManager нуждается в ссылке на DataSource, HibernateTransactionManager нуждается в ссылке на SessionFactory.

Несмотря на то что:

DataSourceTransactionManager свяжет соединение JDBC от указанного источника данных с текущим потоком, потенциально позволяя связать потоковое соединение на каждый источник данных.

Сессия не будет привязана к текущей транзакции, и вам нужны как для локальных транзакций.

Это то, что сделает для вас спящий режим или JPA. Они свяжут контекст персистентности и одно соединение для каждой транзакции.

Если вы выберете транзакции JTA, то внешний TM будет координировать транзакции. DB-соединения будут выходить агрессивно после каждого утверждения, что отлично, если внешний TM всегда будет возвращать одно и то же соединение с тем же потоком в течение глобальной транзакции.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню