Pregunta

He buscado esta pregunta, hay bastantes de ellas aquí en StackOverflow y Google, pero parece que no encuentro nada que funcione para mí.

aquí están mis códigos Spring config: (No uso ningún pointcut, ¿creo que no es necesario?)

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

Tengo una clase de servicio:

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

y una clase de 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 ..
}

Se eliminan algunos detalles innecesarios (por ejemplo, establecedor faltante, etc.), suponga que el código funciona perfectamente bien.

Mi problema con lo anterior es que cuando agregué la línea de excepción de lanzamiento aleatorio, no retrocede, el objeto que se persiste a través del DAO permanece en la base de datos.

Estoy usando Spring 3.1 e Hibernate 3.6 (porque hubo un error con Hibernate 4.0 en Spring 3.1)

¿Pensamientos?

Gracias

¿Fue útil?

Solución 2

Encontré la causa de mi problema y por qué la transacción (aparentemente) no se gestionó correctamente.

En algún lugar de mi 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")
}

La parte donde dice "- Algo de lógica aquí -", se hizo algo de lógica que usa SQL sin formato y llama al ejecutar la actualización:

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

Y debido a que no usa la consulta de Hibernate, y en su lugar usa la ejecución de SQL sin procesar, causó que se llamara a un flush y, por lo tanto, cualquier trabajo realizado antes de la llamada se confirmará junto con eso.

Vuelvo a trabajar el flujo de la lógica para tener en cuenta esta lógica y asegurarme de que la transacción se gestione correctamente.Si bien el uso de SQL sin formato puede ser una indicación de que algo anda mal, era algo necesario que se debía hacer debido a las cosas que el servicio intenta lograr y para mejorar el rendimiento del servicio.

Otros consejos

Ese es el comportamiento previsto de la gestión de transacciones. El comportamiento predeterminado de @Transactional es retroceder solo para excepciones en tiempo de ejecución. Si desea que sus cosas retrocedan después de lanzar DaoException, agréguelas a la lista de excepciones de reversión.No olvide incluir también RuntimeException. Prueba lo siguiente en la clase de Dao @Transactional (propagation= Propagation.Mandatory, rollbackFor= {RuntimeException.class, DaoException.class})

Intente eliminar la anotación @Transactional de la clase DaoImpl.Sospecho que lo que podría estar sucediendo es que la transacción se está comprometiendo cuando vuelve a cruzar ese límite de transacción (DaoImpl).He tenido un éxito desigual con esta configuración.Puede probar diferentes enfoques de transacción para la transacción "interna".

La otra cosa que puede hacer es activar el registro de transacciones de primavera.Piensa en su categoría org.springframework.transaction o algo así.De esa manera, verá exactamente lo que está haciendo w.r.t para revertir y confirmar transacciones ...

No tiene uno de esos controladores JDBC que están en modo AUTOCOMMIT por defecto, ¿verdad?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top