为每个实体使用单独的实体管理员是否会导致问题?

时间:2016-09-08 23:11:08

标签: java jpa eclipselink

我为每个实体类型创建了一个存储库类(一个处理所有jpa方法的类),它拥有自己的entitymanagerfactory。 现在我在多对多的关系中遇到了以下错误:

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.

这种错误在调试时通常不再发生,并且看起来并不一致,这使我相信它可能是管理者之间的同步问题。 (Pk由jpa处理 - @Id @GeneratedValue - 我从未改变过,我确实使用了级联合并)

我目前的假设是正确的,即拥有多个entitymanagerfactories是一个坏主意(可能与我的问题有关)?

2 个答案:

答案 0 :(得分:1)

EntityManagerFactory表示一个持久单元,或者换句话说,一个数据源。如果您没有多个数据源,那么您就不应该创建多重EMF。您可以创建多个EntityManagers(您可以将其视为' connections'到数据库)。

您可以像这样创建EMF -

EntityManagerFactory emf = Persistence.createEntityManagerFactory(
  "objectdb://localhost/myDbFile.odb;user=admin;password=admin")

 EntityManagerFactory emf =
  Persistence.createEntityManagerFactory("myDbFile.odb");

你可以像这样创建EntityManager -

 EntityManager em = emf.createEntityManager();

来自Javadoc - http://docs.oracle.com/javaee/7/api/javax/persistence/EntityManagerFactory.html

  

用于与持久性单元的实体管理器工厂交互的接口。当应用程序完成使用实体管理器工厂和/或应用程序关闭时,应用程序应关闭实体管理器工厂。一旦EntityManagerFactory关闭,其所有实体管理器都被认为处于关闭状态。

添加更多内容,您可能还需要像这样创建的事务 -

try {
    em.getTransaction().begin();
    // Operations that modify the database should come here.
    em.getTransaction().commit();
  }
  finally {
    if (em.getTransaction().isActive())
      em.getTransaction().rollback();
  } 

答案 1 :(得分:0)

我得出的结论是,不同的EMF实际上导致了单独的持久化上下文,这导致了像validationException这样的问题。

(我认为这发生在同一实体的2个不同实例在2个不同的上下文中进行管理,其中一个实例改变了它的状态,虽然我不确定)

像这样测试:

备注:

  • orderweek(=非拥有方)与一周有一对一的双向关系,带有cascadeType.ALL。
  • orderRep和weekRep是执行与Db相关的CRUD语句的实例,每个语句都有自己的实体管理器,由他们自己的EMF创建
  • 2个EMF是在单独的工厂类中创建的,但是链接到同一个DB并且应该使用相同的持久性单元' BreadPU'。
  • 我已经意识到对同一数据源的多个EMF是一个坏主意

(junit测试方法的相关部分)

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