Spring @Transaction не откатывается на исключение - PullRequest
1 голос
/ 18 февраля 2012

Я искал этот вопрос, их довольно много здесь, в StackOverflow и Google, но я не могу заставить что-то работать на меня.

вот мои коды Spring config: (я не использую pointcut - думаю, мне это не нужно?)

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
...
</bean>

<bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
 <property name="dataSource" ref="dataSource" />
 ...
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="hibernateSessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>

У меня есть Класс обслуживания:

@Service
public class ServiceImpl implements ServiceInterface 
{
    /**
     * Injected session factory
     */
    @Autowired(required=true)
    private SessionFactory sessionFactory;

    @Autowired(required=true)
    private Dao myDao;

    /**
     * {@inheritDoc}
     */
    @Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED)
    public void scheduleBlast(BlastParameters blastParameters) throws ServiceException 
    {
        ... do bunch of stuff ..
        myDao.persist(entity)

        if(true)
            throw new ServiceException("random error")
    }

    .. setter methods and other stuff ..
}

и класс Дао:

public class DaoImpl implements DaoInterface
{
    @Autowired(required=true)
    private SessionFactory sessionFactory

    /**
     * {@inheritDoc}
     */
    @Transactional(propagation=Propagation.MANDATORY)
    public void persist(Entity e) throws DaoException
    {
        try
        {
            sessionFactory.getCurrentSession().persist(e);
        }
        catch(Exception ex)
        {
            throw new DaoException(ex);
        }
    }


    .. setter methods and other stuff ..
}

Некоторые ненужные детали удалены (например, отсутствует установщик и т. Д.), При условии, что код работает отлично.

Моя проблема с вышесказанным заключается в том, что когда я добавляю строку исключения случайного выброса, она не откатывается, объект, сохраняемый в DAO, остается в БД.

Я использую Spring 3.1 и Hibernate 3.6 (потому что в Spring 3.1 была ошибка с Hibernate 4.0)

Мысли

Спасибо

Ответы [ 4 ]

11 голосов
/ 29 февраля 2012

Я обнаружил причину своей проблемы и почему транзакция (казалось бы) не удалось должным образом.

Где-то в моем коде

/**
 * {@inheritDoc}
 */
@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED)
public void doWork(Parameters param) throws ServiceException 
{
    ... do bunch of stuff ..
    myDao1.persist(entity)

    -- Some logic here --

    ... do bunch of stuff ..
    myDao2.persist(entity2)

    if(true)
        throw new ServiceException("random error")
}

Часть, где написано "здесь - ", была сделана некоторая логика, которая использует сырой SQL и вызов при выполнении обновления:

Query query = sessionFactory.getCurrentSession().createSQLQuery(queryText);
query.executeUpdate();

И поскольку он не использует запрос Hibernate, а вместо этого использует сырое выполнение SQL, он вызывает сбросвызывается, и поэтому любая работа, выполненная до вызова, будет совершена вместе с ним.

Я перерабатываю поток логики, чтобы учесть эту логику, чтобы убедиться, что транзакция управляется должным образом.Хотя использование необработанного SQL может указывать на то, что что-то не так - это было необходимо сделать из-за того, что служба пытается выполнить, и для повышения производительности службы.

11 голосов
/ 19 февраля 2012

Это предполагаемое поведение управления транзакциями.Поведение по умолчанию для @Transactional - откат только для исключений времени выполнения.Если вы хотите, чтобы ваш материал откатывался после создания DaoException, добавьте его в список исключений отката.Не забудьте также включить RuntimeException.Попробуйте следующее для класса Dao @Transactional (распространение = Propagation.Mandatory, rollbackFor = {RuntimeException.class, DaoException.class})

1 голос
/ 18 февраля 2012

Попробуйте удалить аннотацию @Transactional из класса DaoImpl. Я подозреваю, что может происходить то, что транзакция фиксируется, когда она пересекает границу этой транзакции (DaoImpl). Я имел смешанный успех с этой настройкой. Вы можете попробовать несколько разных подходов к транзакции к «внутренней» транзакции.

Другая вещь, которую вы можете сделать, это включить весеннее ведение журнала транзакций. Он думает, что его категория org.springframework.transaction или что-то. Таким образом, вы увидите, что именно делает w.r.t для отката и фиксации транзакций ...

0 голосов
/ 18 февраля 2012

у вас нет одного из тех драйверов JDBC, которые по умолчанию находятся в режиме AUTOCOMMIT?

...