java – JPA:如果EntityManager关闭,为什么会加载惰性字段

我使用
eclipselink并拥有以下代码:

public Temp getTemp() {
    EntityManager em=emf.createEntityManager();
    String queryString="SELECT a FROM Temp a";
    EntityGraph<Temp> eg = em.createEntityGraph(Temp.class);
    eg.addAttributeNodes("id");
    //eg.addAttributeNodes("name");
    Query query = em.createQuery(queryString);
    query.setHint("javax.persistence.fetchgraph", eg);
    List<Temp> items=query.getResultList();
    em.close();// ENTITYMANAGER IS CLOSED 
    return items.get(0);
}

public void temp(){
    Temp temp=getTemp();
    System.out.println("id:"+temp.getId());
    System.out.println("name:"+temp.getName());
}

从代码中可以看出,我们只加载id.但是,当我们执行temp.getName()时,执行SQL查询并加载必要的数据.为什么?我们做了关闭实体经理.我希望在temp.getName()中获得异常.

编辑1
经过一些研究后我发现了以下内容 – 当我编织静态时,我上面描述的行为是实际的(< property name =“eclipselink.weaving”value =“static”/> de.empulse.eclipselink weaving plugin).但是,当编织是动态的(< property name =“eclipselink.weaving”value =“true”/>)时,我会得到异常:

java.lang.ClassNotFoundException: org.eclipse.persistence.internal.jpa.EntityManagerImpl not found by com.temp [57]
    at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1574)
    at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:79)
    at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:2018)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at com.temp.Temp._persistence_checkFetched(Temp2.java)
    at com.temp.Temp._persistence_get_name(Temp2.java)
    at com.temp.Temp.getName(Temp.java:44)

所以问题就在这里:Eclipselink: Difference between static and dynamic weaving

最佳答案 因为那是EclipseLink并且它支持分离的字段加载…即不在JPA规范中并且完全不可移植的东西(即在其他实现中不支持).它的“分离”状态并非真正“分离”,并保留与EntityManagerFactory的联系.如果你关闭EMF,那么他们就会真正“脱离”.

this email chain discussing the “feature”.它没有提到关闭它的方式(所以你可以有便携行为),并且实际上要求该人请求它!关于为什么JPA TCK不检查可移植行为的问题是要求Oracle的问题……但是,请继续,EclipseLink团队写的TCK不是他们……嗯……

为了保持便携性,您将根据JPA规范进行分离,而不是依赖此类行为

点赞