Monday 12 September 2011

Transaction VS Extended Persistence Context Type

This article uses code examples to illustrate the difference between TRANSACTION and EXTENDED persistence context type.

Firstly create an entity class

@Entity
@Table(name="T_PERSON")
public class Person{
    
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    
    @Column(name = "NAME")
    private String name;
    
    public Person() {
        super();
    }
    
    public Person(String name) {
        super();
        this.name = name;
    }
}

Create a TRANSACTION persistence context type in a stateful session bean.

@Stateful(name="transactionPersistenceContextBean")
@Local(TransactionService.class)
public class TransactionPersistenceContextBean 
    implements TransactionService {

    @PersistenceContext(unitName="unit", 
            type=PersistenceContextType.TRANSACTION)
    private EntityManager em;
    
    private Person person;
    
    @Override
    public void save(String name) {
        person = new Person(name);
        em.persist(person);
    }

    @Override
    public void update(String name) {
        person.setName(name);
        em.flush();
    }
}

Create an EXTENDED persistence context type in a stateful session bean.

@Stateful(name="extendedPersistenceContextBean")
@Local(TransactionService.class)
public class ExtendedPersistenceContextBean 
    implements TransactionService {

    @PersistenceContext(unitName="unit", 
            type=PersistenceContextType.EXTENDED)
    private EntityManager em;
    
    private Person person;
    
    @Override
    public void save(String name) {
        person = new Person(name);
        em.persist(person);
    }

    @Override
    public void update(String name) {
        person.setName(name);
        em.flush();
    }
}

Create a servlet to test

public class PersistenceContextServlet
   extends HttpServlet {
    
    @EJB(beanName="transactionPersistenceContextBean")
    //@EJB(beanName="extendedPersistenceContextBean")
    private TransactionService service;
    
    @Override
    protected void doGet(HttpServletRequest req, 
            HttpServletResponse resp)
            throws ServletException, IOException {
        service.save("abcde");
        service.update("defgh");
    }
}

The result for TRANSACTION Persistence Context


The result for EXTENDED Persistence Context


For TRANSACTION Persistence Context type, when the save method is complete, person instance is detached. So when the update method is invoked, person instance is not associated with the database session. So any changes made to person instance cannot be synchronized to the database.

For EXTENDED Persistence Context type, when the save method is complete, person instance is still managed by the database session. So when the update method is invoked, any changes made to person instance will be synchronized to the database.

So how can we update person instance in the case of TRANSACTION Persistence Context type?

By merging person instance so that person instance is managed by the database session.

public void update(String name) {
    person = em.merge(person);
    person.setName(name);
    em.flush();
}

The result:


Note: Only the returned object by merge method is associated with the database session.

e.g. if the update method is changed to

public void update(String name) {
    em.merge(person);
    person.setName(name);
    em.flush();
} 

The result:


This is because the above person instance is not managed by database session.