问题
My @Transactional annotation doesn't rollback the first insert when the second update sentence fails (with a non-RuntimeException
). The exception is launched in updateNumeroVotos
but Spring doesn't rollback the insert of save operation.
Any idea?
I have these files:
IdeaService.java
code:
@Service
public class IdeasServiceImpl implements IdeasService {
@Autowired
all daos code
/**
* Metodo que inserta un voto de un usuario
*/
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void incorporarVoto(String token, Integer id) throws Exception {
IdeaVotoVO ideaVoto = new IdeaVotoVO();
ideaVoto.setUsuario(usuariosService.getDatosTokenUsuario(token).getLoginCiudadano());
ideaVoto.setIdIdea(id);
ideaVoto.setVoto(ConstantesModel.IDEA_VOTO_POSITIVO);
if (validarVoto(ideaVoto)) {
ideaVotoDAO.save(ideaVoto);
ideaDatosDao.updateNumeroVotos(new Timestamp(Generic.getFechaActual()), id);
}
}
applicationContext.xml
<mvc:annotation-driven />
<mvc:default-servlet-handler />
<context:component-scan base-package="example.code.xxxx.*" />
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@ora11g:1521:xxxxxx" />
<property name="username" value="xxxxxx" />
<property name="password" value="yyyyy" />
<property name="validationQuery" value="SELECT SYSDATE FROM DUAL" />
<property name="maxIdle" value="3" />
<property name="poolPreparedStatements" value="true" />
<property name="maxOpenPreparedStatements" value="100" />
<property name="maxWaitMillis" value="10000" />
<property name="maxTotal" value="20" />
</bean>
<bean id="sessionFactoryCiud"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
</props>
</property>
<property name="mappingResources">
<list>
<<--Here de entity's-->
</list>
</property>
</bean>
<cache:annotation-driven />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehcache" />
</bean>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="classpath:ehcache.xml" />
<bean id="TransactionManagerCiud"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactoryCiud" />
<qualifier value="ciudada" />
</bean>
<tx:annotation-driven transaction-manager="TransactionManagerCiud" proxy-target-class="true"/>
<bean id="ideasService"
class="example.code.xxxx.service.ideas.impl.IdeasServiceImpl">
</bean>
<bean id="IdeaVotoDAO"
class="example.code.xxxx.model.ideas.impl.IdeaVotoDAOImpl">
<property name="sessionFactory" ref="sessionFactoryCiudadania" />
</bean>
<bean id="IdeaDatosDAO"
class="example.code.xxxx.model.ideas.impl.IdeaDatosDAOImpl">
<property name="sessionFactory" ref="sessionFactoryCiud" />
</bean>
</beans>
I tried to add this lines but it dont work
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" rollback-for="Exception"/>
</tx:attributes>
</tx:advice>
回答1:
Then, please add:
rollbackFor = Exception.class
to your @Transactional
annotation.
EDIT:
If you don't want to edit each of your @Transactional
annotatinos, please look at this interesting approach.
From the start a good design would be, if (all of) your services would throw (a customized type of) RuntimeException, when something rollbackable happens. (But this seems more complex than modifying all annotations.)
回答2:
You can provide tx:advice
s for the transaction managers like this:
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" rollback-for="Exception"/>
</tx:attributes>
</tx:advice>
(as explained in the documentation.)
回答3:
What is "sessionFactoryCiudadania" used by "ideaVotoDao" and why is it different from the SessionFactory used by your transaction manager? The annotation is only going to rollback content from the session that it created.... If a DAO is using a different session internally it's going to commit based on its own rules (which probably means basic autoCommit mode.)
来源:https://stackoverflow.com/questions/29955159/spring-transactional-annotation-does-not-roll-back