java - localcontainerentitymanagerfactorybean - El método @Transactional llamado desde otro método no obtiene una transacción
spring jpa hibernate (3)
En Spring, un método que se anota con @Transactional
obtendrá una nueva transacción si aún no existe, pero noté que un método transaccional no obtiene ninguna transacción si se llama desde uno no transaccional. Aquí está el código.
@Component
public class FooDao {
private EntityManager entityManager;
@PersistenceContext
protected void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Transactional
public Object save(Object bean) {
return this.entityManager.merge(bean);
}
public Object saveWrap(Object bean) {
return save(bean);
}
}
@Component
public class FooService {
private FooDao fooDao;
public void save(Object bean) {
this.fooDao.saveWrap(bean); // doesn''t work.
this.fooDao.save(bean); // works
}
}
saveWrap()
es un método regular que llama a save()
que es transaccional, pero saveWrap()
no persistirá ningún cambio.
Estoy usando Spring 3 e Hibernate 3. ¿Qué estoy haciendo mal aquí? Gracias.
Es una de las limitaciones de Springs AOP. Debido a que el dao bean es de hecho un proxy cuando se crea por spring, esto significa que llamar a un método desde la misma clase no llamará al consejo (que es la transacción). Lo mismo ocurre con cualquier otro punto de corte.
Esto es un poco tarde, lo sé, pero me gustaría agregar una manera de superar esta limitación es que, dentro del método, obtenga el bean spring del contexto de la aplicación e invoque el método. Cuando el bean spring se obtiene del contexto de la aplicación, será el bean proxy, no el bean original. Como el bean proxy ahora está invocando el método en lugar del bean original, se implementarán los consejos de transacción en él.
Sí, este es el comportamiento esperado. @Transactional
le dice a spring que cree un proxy alrededor del objeto. El proxy intercepta llamadas al objeto desde otros objetos. El proxy no intercepta llamadas dentro del objeto.
Si desea que esto funcione, agregue @Transactional
en el método que se invoca desde "afuera".