JPA Entity Found by Search in Advanced Ejb State Not Managed

I thought the object found by em.find is automatically controlled by em, even from a transaction, but this class below seems to show the opposite. Was I wrong or what was the mistake in this class?

@Stateful @TransactionAttribute(NOT_SUPPORTED) public class CustomerGateway { @PersistenceContext(unitName = "customersPU", type = EXTENDED) private EntityManager em; private Customer customer; public Customer find(Long id) { // customer is not managed! this.customer = em.find(Customer.class, id); // Print false! System.out.println("Method find: " + em.contains(customer)); // Print false too (2 is the id of an entity)! System.out.println("Method find: " + em.contains(em.find(Customer.class, 2L)); // A workaround customer = em.merge(customer); // Print true. System.out.println("Method find after merge: " + em.contains(customer)); return this.customer; } 

EDIT 1: Object Code

 @Entity @NamedQuery(name = "Customer.all", query = "select c from Customer c") public class Customer implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; public Customer() { } public Customer(String name) { this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode() { int hash = 0; hash += (id != null ? id.hashCode() : 0); return hash; } @Override public boolean equals(Object object) { // TODO: Warning - this method won't work in the case the id fields are not set if (!(object instanceof Customer)) { return false; } Customer other = (Customer) object; if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { return false; } return true; } @Override public String toString() { return "entity.Customer[ id=" + id + " ]"; } } 

EJB Status Code:

 @Stateful @TransactionAttribute(NOT_SUPPORTED) public class CustomerGateway { @PersistenceContext(type = PersistenceContextType.EXTENDED) private EntityManager em; private Customer customer; public Customer getCustomer() { return customer; } public void create(Customer customer) { em.persist(customer); this.customer = customer; } public Customer find(Long id) { this.customer = em.find(Customer.class, id); System.out.println("customer managed ? " + em.contains(this.customer)); // Workaround : // this.customer = em.merge(customer); return customer; } public void remove(Long id) { Customer cust = em.getReference(Customer.class, id); em.remove(cust); } @TransactionAttribute(REQUIRES_NEW) public void save() { } public List<Customer> findAllCustomers() { Query query = em.createNamedQuery("Customer.all"); return query.getResultList(); } @Remove public void close() { } } 

I work with NetBeans 7.4, GlassFish 4.0, EJB 3.2, Java DB.

+6
source share
2 answers

According to Checkus, this seems like a bug in GF4: https://java.net/jira/browse/GLASSFISH-20968

0
source

Everything you have tested is in accordance with the specification. The save context is retained (and the objects remain attached) as long as the transaction exists. Thus, in the extended persistence and transaction NOT_SUPPORTED objects retrieved when the search method is invoked are filtered out. -Also, if your Customer object has a lazy relationship and you are trying to access them, then it is very likely that you will get an exception at runtime.

Now, why is the merge method ok ?. First, remember that merge returns a managed entity and binds the client to a persistence context.

Secondly, you have an EXTENDED persistent context, so it will not update the database until you call the annotated @Remove method. When this call arrives, you are likely to receive a TransactionRequiredException .

EDIT 1 --------------------------------------------- --- --------------------------------

According to your comments:

  • find not required in the transaction, although if you need a managed object, it must be one.

  • The paragraph refers to the life cycle (section 3.3), in this case it tries to explain that at the end of the method for the bean transaction area, the objects will be detached, but in the case of an extended EM, the objects will remain attached.

  • There are two insightful paragraphs:

  • When an EM with an extended persistence context is used, the hold, delete, merge, and update operations can be invoked regardless of whether the transaction is active. The effects of these operations will be tied to the database when the extended save context is credited to the transaction and the transaction commits.

  • The save context is closed by the container when the @Remove method of a session with a bean state ends (or an instance of a session with a bean state).

  • It looks like the method that you first omit in the question using @TransactionAttribute(REQUIRES_NEW) is the place where the merge is successful. That is why you have no exception.

EDIT 2 --------------------------------------------- --- --------------------------------

After some testing, GF4 has an error, and> https://java.net/jira/browse/GLASSFISH-20968 was reported

EDIT 3 --------------------------------------------- --- ---------------------------------

May 20/2014: the error was noted as: must be fixed for Glassfish 4.0.1.

+2
source

All Articles