Wouter Wouter - 1 year ago 73
Java Question

Does using a seperate entitymanagerfactory for each entity cause problems?

I've made a repository class (a class that handles all jpa methods) for each entity type with it's own entitymanagerfactory.
Now I've encountered the following error on my many to many relationship:

[junit][EclipseLink-7251] Exception Description: The attribute [ID] of class [Person] is mapped to a primary key column in the database. Updates are not allowed.

This error often doesn't occur anymore when debugging and doesn't seem to appear consistently, which leads me to believe it might be a sync issue between managers. (the Pk is handled by jpa - @Id @GeneratedValue - and never changed by me, i do use cascade merge though)

Am I correct in my current assumption that having multiple entitymanagerfactories is a bad idea (and might be related to my problems)?

Answer Source

I have come to the conclusion that the different EMFs did in fact cause seperate persistence contexts, which caused problems like the validationException.

(I think this happened when 2 different instances of the same entity were managed in 2 different contexts and one of the instances changed it's state though i'm not certain)

Tested like this:


  • orderweek (= non-owning side) has a one to one bidirectional relationship with week with a cascadeType.ALL.
  • orderRep and weekRep are instances executing CRUD statements related to the Db, each with their own entity manager, created from their own EMF
  • The 2 EMF's are created in seperate factory-classes, but linked to the same DB and should be using the same Persistence Unit 'BreadPU'.
  • I have since realized that multiple EMF's to the same data source is a bad idea

(relevant part of a junit test method)

OrderBill cheapOrder = new OrderBill(5, LocalDate.now());
//because of the cascade, both the cheapOrder and the week or now persisted in the DB and managed by weekRep

OrderBill dbOrder = orderRep.updateOrder(cheapOrder);
boolean t2 = weekRep.isManaged(cheapOrder); //true
boolean t3  = orderRep.isManaged(cheapOrder); //false
//It's because this returns false I assume both persistence contexts are different
boolean t4 =  orderRep.isManaged(dbOrder); //true
//If i now use "cheapOrder" to change the order i get the error
//If i now use "dbOrder" to change the order, db gets updated as expected