Domanda

Ho cercato in giro questa domanda, ce ne sono alcune qui su StackOverflow e Google ma non riesco a trovare nulla che funzioni per me.

ecco i miei codici Spring config: (Non uso alcun pointcut - penso di non averne bisogno?)

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

Ho una classe Service:

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

Alcuni dettagli non necessari vengono eliminati (es. setter mancante, ecc.), supponendo che il codice funzioni perfettamente.

Il mio problema con quanto sopra è che quando ho aggiunto la riga di eccezione casuale di lancio, non viene eseguito il rollback, l'oggetto che viene persistito tramite DAO rimane nel db.

Sto usando Spring 3.1 e Hibernate 3.6 (perché c'era un bug con Hibernate 4.0 su Spring 3.1)

Pensieri?

Grazie

È stato utile?

Soluzione 2

Ho trovato la causa del mio problema e il motivo per cui la transazione (apparentemente) non è stata gestita correttamente.

Da qualche parte nel mio codice

/**
 * {@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 in cui si dice "- Some logic here -", è stata eseguita una logica che utilizza SQL grezzo e chiama in esecuzione aggiornamento:

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

E poiché non utilizza la query Hibernate e invece utilizza l'esecuzione SQL non elaborata, ha causato la chiamata di un flush e quindi qualsiasi lavoro svolto prima della chiamata verrà eseguito insieme a esso.

Rielaboro il flusso della logica per tenere conto di questa logica per assicurarmi che la transazione sia gestita correttamente.L'utilizzo di SQL grezzo potrebbe indicare che c'è qualcosa di sbagliato: era necessario fare qualcosa a causa delle cose che il servizio cerca di realizzare e per migliorare le prestazioni del servizio.

Altri suggerimenti

Questo è il comportamento previsto della gestione delle transazioni. Il comportamento predefinito per @Transactional è il rollback solo per le eccezioni di runtime. Se vuoi che le tue cose vengano ripristinate dopo aver lanciato DaoException, aggiungile all'elenco delle eccezioni di rollback.Non dimenticare di includere anche RuntimeException. Prova quanto segue sulla classe Dao @Transactional (propagation= Propagation.Mandatory, rollbackFor= {RuntimeException.class, DaoException.class})

Prova a rimuovere l'annotazione @Transactional dalla classe DaoImpl.Sospetto che ciò che potrebbe accadere sia che la transazione venga commessa quando ritorna oltre il confine della transazione (DaoImpl).Ho avuto un successo misto con questa configurazione.Puoi provare diversi approcci di transazione alla transazione "interna".

L'altra cosa che puoi fare è attivare la registrazione delle transazioni primaverili.Pensa alla sua categoria org.springframework.transaction o qualcosa del genere.In questo modo vedrai esattamente cosa sta facendo con il rollback e il commit delle transazioni ...

you don't have one of those JDBC drivers that are in AUTOCOMMIT mode by default, do you?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top