Pergunta

Eu pesquisei por essa questão, há alguns deles aqui no StackOverflow e no Google, mas não consigo fazer nada funcionando para mim.

aqui estão meus códigos Configuração do Spring: (eu não uso nenhum pointcut - acho que não preciso?)

<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"/>

Eu tenho uma aula de serviço:

@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 ..
}

e uma classe Dao:

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 ..
}

Alguns detalhes desnecessários são eliminados (por exemplo, setter ausente, etc), assuma que o código funciona perfeitamente.

Meu problema com o acima é que quando adicionei a linha de exceção aleatória, ela não faz rollback, o objeto que está sendo persistido por meio do DAO permanece no banco de dados.

Estou usando Spring 3.1 e Hibernate 3.6 (porque havia um bug com Hibernate 4.0 no Spring 3.1)

Pensamentos?

Obrigado

Foi útil?

Solução 2

Encontrei a causa do meu problema e por que a transação (aparentemente) não foi gerenciada corretamente.

Em algum lugar no meu código

/**
 * {@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")
}

A parte onde diz "- Alguma lógica aqui -", foi feita alguma lógica que usa SQL bruto e chama na execução de atualização:

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

E como não está usando a consulta do Hibernate e, em vez disso, está usando a execução de SQL bruta, causou a chamada de um flush e, portanto, qualquer trabalho feito antes da chamada será confirmado junto com isto.

Eu refaço o fluxo da lógica para levar em conta essa lógica para garantir que a transação seja gerenciada corretamente.Embora o uso de SQL bruto possa ser uma indicação de que há algo errado - era algo necessário a ser feito devido às coisas que o serviço tenta realizar e para melhorar o desempenho do serviço.

Outras dicas

Esse é o comportamento pretendido do gerenciamento de transações. O comportamento padrão para @Transactional é reverter apenas para exceções de tempo de execução. Se você quiser que seu material seja revertido após lançar DaoException, adicione-o à lista de exceções de reversão.Não se esqueça de incluir também RuntimeException. Experimente o seguinte na classe Dao @Transactional (propagation= Propagation.Mandatory, rollbackFor= {RuntimeException.class, DaoException.class})

Tente remover a anotação @Transactional da classe DaoImpl.Eu suspeito que o que pode estar acontecendo é que a transação está sendo confirmada quando cruza de volta o limite da transação (DaoImpl).Tive sucesso misto com esta configuração.Você pode tentar algumas abordagens de transação diferentes para a transação "interna".

A outra coisa que você pode fazer é ativar o registro de transações do spring.Acho que sua categoria org.springframework.transaction ou algo assim.Dessa forma, você verá exatamente o que ele está fazendo para reverter e confirmar as transações ...

você não tem um daqueles drivers JDBC que estão no modo AUTOCOMMIT por padrão, tem?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top