Patrones de diseño ... DAO? Hibernate? transaccionalidad?

¿Como estan todos?

Ojala me puedan ayudar con la siguiente duda...

Estoy creando una aplicación con jsf, spring y hibernate. En ella tengo una clase BO que implementa una inteface BO y una clase DAO que implementa una interface DAO.

La cuestion es acerca de la transaccionalidad, en algun lugar lei que en los DAOs se deben de crear solo operaciones atomicas, es decir sin transacciones.

Segun esto este codigo estaria mal implementado porque se inician las transacciones directamente en BO y no en los DAOs

@Service
public class VentaProductoBO implements IVentaProductoBO {
       
       
        @Autowired
        private VentaProductoDAO ventaProductoDAO;

       @Autowired
        private promocionDAO promocionDAO;
       
        @Autowired
        private SessionFactory sessionFactory;

       
       
        public void guardarIngrediente(String nombre){
               
               
                Session session = sessionFactory.openSession();
                Transaction tran = session.beginTransaction();  // transaccion en hibernate

                Venta ventaVO = new Venta();
                ventaVO setVenta(venta);
                altaIngredientesDAO.guardar(session,ventaVO);

               
                Promocion ventaVO = new Promocion();
                PromocionVO setPromocion(venta);
                PromocionDAO.guardar(session,PromocionVO);
               

                 tran.commit(); // commit en hibernate
                 
                //obviando el rollback si existe un error
               
                session.close();
        }
}

Pero si se realizara esto en los DAO entonces dejarian de ser atomicas, ya que se estarian guardando en la misma clase dos tipos de objetos diferentes (Promocion y Ventas).

Como se resuelve esto correctamente?

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

No creo que haya una

No creo que haya una restricción para que un dao participe en una transacción, pero si quisieras adherite a esa definición puedes crear otro dao y dejar que este sea el encargado de hacer la transacción. Desde fuera tu operación sigue siendo atómica.

..
class VentaProductoDAO implements IVentaProductoDAO {
      //@Autowires aca
     public void guarda( Session session, Venta ventaVO, Promocion promocionVO ) {
          Transaction t = session.beginTransaction();
         ....
         ingredientesDAO.guarda(session, ventaVO);
         ...
         promocionDAO.guarda(session, promocionVO);
         t.commit();
         
     }
}
class VentaProductoBO implements IVentaProductoBO {
       ....
     public void guardaIngredientes( String nombre ) {
         Session session = sessionFactory.openSession();

         Venta ventaVO = new Venta();
         ventaVO.setVenta(venta);

         Promocion promocionVO = new Promocion();
         promocionVO.setPromocion( venta )

         ventaProductoDAO.guarda(session, ventaVO, promovcionVO); /// <--- ohhh atomica! magia...
         session.close();
     }
}

Si te fijas es básicamente lo mismo que lo que estabas haciendo antes en el BO, pero solo moviéndolo a otra clase que sea un "DAO" y para el cliente de esta clase la operación parece atómica.

Imagen de ezamudio

rollback

Pongas donde pongas ese código, si lo pones así nada más, está mal. No estás cachando ninguna excepción, no contemplas la posibilidad de rollback; para qué te molestas en hacer una transacción?

Si ocurre una excepción, la transacción se va a quedar abierta; nadie le está dando rollback. El rollback o commit debe ir en un finally. O puedes usar transaccionalidad declarativa, ya sea de Spring o tal vez la versión de Hibernate que usas ya traiga algo para ayudarte con eso.

Imagen de sr.bug

gracias por responder

Si se que no estoy cachando ninguna excepcion, puse en un comentario " //obviando rollback si hay error " o algo asi realmente no es un fragmento de mi codigo todo es dummy solo lo puse para ejemplificar.

Saludos.