我使用 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
编织插件)。但是,当编织是动态的(<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 规范分离并且不依赖于此类行为
关于java - JPA:如果 EntityManager 关闭,为什么加载惰性字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37740886/