Joey
Joey

Reputation: 121

CDI Beans and JPA Transactions

Shall a bean which is for instance used as cdi application scoped contain jpa read/write stuff or should I use always EJB for db stuff? I read somewhere on the internet that cdi shall not contain db stuff. Is that true?

Upvotes: 3

Views: 4355

Answers (2)

Rouliboy
Rouliboy

Reputation: 1377

YES, you can manage db stuffs on CDI beans using @Transactional InterceptorBinding if you are on any JavaEE 7 plus editions or JakartaEE

Take a look at the Javadoc : @Transactional

Here are the steps to inject EntityManager with CDI without EJB

  1. First create a producer to produce the EntityManager.

    public class EntityManagerProducer {
      @PersistenceContext(name = "customer-orders-unit")    
      private EntityManager em;
    
      @Produces
      @RequestScoped
      public EntityManager getEntityManager() {
        return em;
      }
    }
    
  2. Create your bean to do DAO actions.

    public MyCDIBeanDao{
      @Inject
      private EntityManager m_entityManager;
    
      @Transactional
      public doStuff(){
        // Here you are in a Container managed Transaction
        m_entityManager.persist(...)
      }
    }
    
  3. Don't forget to add beans.xml in your WEB-INF folder.

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
           xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
           http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd" 
           bean-discovery-mode="all" 
           version="2.0">
    </beans>
    

Upvotes: 8

Alboz
Alboz

Reputation: 1851

As always the answer is it depends... It depends on your specific use case.

In Java EE we use @EJB beans as the place where we Inject the EntityManager to later perform read/write on JPA Entities. Why we do this? Because we need Transactions. By default when you annotate a bean with @Stateless all the methods in it are Transactional and you get it all for free. Transactions enable you to update multiple tables in an atomic fashion, they will either succeed all or fail.

Example: In your method updateABC()you want to update Table A,B,C and you want all of them to succeed or the transaction to be Roll-backed:

@Stateless
public class MyClass{
    @PersistenceContext
    EntityManager em;

    public void updateABC(){
       A a= em.find(A.class, aId);
       //here update some fields on the entity "a"

       B b= em.find(B.class, bId);
       //here update some fields on the entity "b"
       C c= em.find(C.class, cId);
       //here update some fields on the entity "c"
    }
}

And this is it... you're done. All your updates will be magically persisted to the DB or nothing.

Do you need something like this? Go for EJB's. You need not? You want to do the job manually? then create your own beans...

Upvotes: 4

Related Questions