Reputation: 322
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:
ValidationException
[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)?
Upvotes: 0
Views: 139
Reputation: 322
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:
notes:
(relevant part of a junit test method)
OrderBill cheapOrder = new OrderBill(5, LocalDate.now());
weekRep.addWeek(cheapOrder.getOrderWeek());
//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
Upvotes: 0
Reputation: 1199
EntityManagerFactory represents one persistent unit or in other words one data source. If you don't have multiple datasources then you shouldn't create multipe EMF. You can create multiple EntityManagers though (which you can think of like 'connections' to database).
You create EMF like this -
EntityManagerFactory emf = Persistence.createEntityManagerFactory(
"objectdb://localhost/myDbFile.odb;user=admin;password=admin")
or
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("myDbFile.odb");
and you create EntityManager like this -
EntityManager em = emf.createEntityManager();
From Javadoc - http://docs.oracle.com/javaee/7/api/javax/persistence/EntityManagerFactory.html
Interface used to interact with the entity manager factory for the persistence unit.When the application has finished using the entity manager factory, and/or at application shutdown, the application should close the entity manager factory. Once an EntityManagerFactory has been closed, all its entity managers are considered to be in the closed state.
Adding more, you might need Transactions as well which you would create like this -
try {
em.getTransaction().begin();
// Operations that modify the database should come here.
em.getTransaction().commit();
}
finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
}
Upvotes: 1