transaction management example driven annotation and hibernate spring-mvc service controller transactional

hibernate - management - ¿Por qué usar @Transactional con @Service en lugar de con @Controller?



spring transaction propagation (4)

He visto muchos comentarios en artículos de desbordamiento de pila. Encontré ciertas cosas acerca del uso de @Transactional con @Service o con @Controller.

"Por lo general, uno debe poner una transacción en la capa de servicio".

"El caso normal sería anotar en un nivel de capa de servicio"

"Piensa que las transacciones pertenecen a la capa de servicios. Es la que conoce unidades de trabajo y casos de uso. Es la respuesta correcta si tienes varios DAO inyectados en un servicio que necesitan trabajar juntos en una sola transacción". [Fuente]

Desventaja para usar @transactional con @service layer

Si tuviera 2 métodos, por ejemplo saveUser () y saveEmail () (porque almaceno los correos electrónicos en una base de datos para enviarlos más tarde, como una cola) crearía en mi servicio un método saveUserAndSendEmail (usuario) que sería transaccional. [Fuente]

Significa que creo muchos métodos en la capa de servicio en lugar de uno Save Generic Method como sigue

public <T> long save(T entity) throws DataAccessException { Session session = sessionFactory.getCurrentSession(); long getGenVal=(Long) session.save(entity); return getGenVal; }

De acuerdo con la solución anterior, significa que tenemos muchos métodos como seguir LOL ...

public <T> long saveAccount(T entity)....

public <T> long saveWithAuditLog(T entity, K entity1)....

public <T> long saveWithAuditLogAndEntries(T entity, K entity, M entity)....

VENCER esta situación

UTILIZO @Transactional en @Controller y solo realizo un Método de guardado genérico y guardo todas las entidades / modelo usando este sencillo método de guardar. y si algún método no se guarda, todas las transacciones en la reversión del controlador se realizarán correctamente.

Otra situación que garantiza que @Transactional se use con @Controller

En @Controller:

pt.save(entity1); pt.save(entity2); int a = 2/0; pt.save(entity3);

En el caso, @Transactional on Service, las primeras 2 entidades se guardaron con éxito pero en tercer lugar no se revierte toda la transacción

En el caso, @Transactional en @Controller se produce toda la reversión de la transacción como excepción

por qué el desbordamiento de pila preguntó: "No haga transacciones en su controlador. Póngalos en sus clases de capa de servicio". [fuente]


Creé un servicio de capa superior que usa otros servicios (no transaccionales). Y el servicio de capa superior es transaccional.

@Service public class Service1Impl implements Servcie1 { public Object method11(){...} public Object method12(){...} } @Service public class Service2Impl implements Service2 { public method21(){...} } public interface Service1 { public Object method11(); public Object method12(); } public interface Service2 { public Object method21(); } @Transactional public interface UpperLayerService {} @Service public class UpperLayerServiceImpl implements UpperLayerService { @Autowired private Service2 service2; @Autowired private Service3 service3; public Object doWork() { Object o1 = service1.method11(); Object o2 = service1.method12(); Object o3 = service2.method21(); .... Object res = null;//...Any code return res; } }


El controlador está firmemente en la capa de visualización, que se puede cambiar en cualquier momento. El servicio aún posee unidades de trabajo y debería funcionar correctamente independientemente de a qué vista acceda. Mi respuesta aquí sigue en pie.


Está preguntando acerca de las mejores prácticas, y la mejor práctica es marcar @Transactional en la capa de servicio porque un @Controller no debe estar al tanto de la persistencia de datos en una lógica MVC.
@Service se construye sobre casos de uso generados a partir del análisis y conoce la unidad de trabajos y también se realiza pensando en términos de reutilización: si cambia de un contexto web a uno de escritorio (por ejemplo, o alguna otra interfaz visual) donde @Controller capa de @Controller no existe, no tienes problemas porque todo está encapsulado en la capa de servicio.
Un @Service es un contrato y una modificación en la capa de presentación no debería requerir una reescritura del código @Service .
Pero a Spring no le importa dónde coloque los límites de su transacción, puede poner @Controller pero su aplicación puede ser más difícil de mantener.

Espero que esto sea lo suficientemente claro. Lo siento si no; El inglés no es mi lengua materna


solo para que otros lo sepan, se desaconsejan las anotaciones de interfaz

Spring recomienda que solo anote clases concretas (y métodos de clases concretas) con la anotación @Transactional, en lugar de anotar las interfaces. Ciertamente puede colocar la anotación @Transactional en una interfaz (o un método de interfaz), pero esto funciona solo como lo esperaría si está utilizando proxys basados ​​en interfaz. El hecho de que las anotaciones de Java no se hereden de las interfaces significa que si está utilizando proxies basados ​​en clases (proxy-target-class = "true") o el aspecto basado en weaving (mode = "aspectj"), entonces la configuración de la transacción es no reconocido por la infraestructura de proxying y weaving, y el objeto no estará envuelto en un proxy transaccional, lo cual sería decididamente malo.