Java 如何测试延迟加载的 JPA 集合是否已初始化?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4306463/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to test whether lazy loaded JPA collection is initialized?
提问by akira
I have a service that gets a JPA entity from outside code. In this service I would like to iterate over a lazily loaded collection that is an attribute of this entity to see if the client has added something to it relative to the current version in the DB.
我有一个从外部代码获取 JPA 实体的服务。在这个服务中,我想遍历一个延迟加载的集合,这个集合是这个实体的一个属性,看看客户端是否相对于数据库中的当前版本向它添加了一些东西。
However, the client may have never touched the collection so it's still not initialized. This results in the well known
但是,客户端可能从未接触过该集合,因此它仍未初始化。这导致众所周知的
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.SomeEntity.
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.SomeEntity.
Of course, if the client never touched the collection, my service doesn't have to check it for possible changes. The thing is that I can't seem to find a way to test whether the collection is initialized or not. I guess I could call size()
on it and if it throws LazyInitializationException
I would know, but I'm trying not to depend on such patterns.
当然,如果客户端从未接触过该集合,我的服务就不必检查它是否有可能发生的变化。问题是我似乎无法找到一种方法来测试集合是否已初始化。我想我可以调用size()
它,如果它抛出LazyInitializationException
我会知道,但我尽量不依赖于这种模式。
Is there some isInitialized()
method somewhere?
有isInitialized()
什么方法吗?
采纳答案by dira
Are you using JPA2?
您使用的是 JPA2 吗?
PersistenceUnitUtil
has two methods that can be used to determine the load state of an entity.
PersistenceUnitUtil
有两种方法可用于确定实体的加载状态。
e.g. there is a bidirectional OneToMany/ManyToOne relationship between Organization and User.
例如,组织和用户之间存在双向的一对多/多对一关系。
public void test() {
EntityManager em = entityManagerFactory.createEntityManager();
PersistenceUnitUtil unitUtil =
em.getEntityManagerFactory().getPersistenceUnitUtil();
em.getTransaction().begin();
Organization org = em.find(Organization.class, 1);
em.getTransaction().commit();
Assert.assertTrue(unitUtil.isLoaded(org));
// users is a field (Set of User) defined in Organization entity
Assert.assertFalse(unitUtil.isLoaded(org, "users"));
initializeCollection(org.getUsers());
Assert.assertTrue(unitUtil.isLoaded(org, "users"));
for(User user : org.getUsers()) {
Assert.assertTrue(unitUtil.isLoaded(user));
Assert.assertTrue(unitUtil.isLoaded(user.getOrganization()));
}
}
private void initializeCollection(Collection<?> collection) {
// works with Hibernate EM 3.6.1-SNAPSHOT
if(collection == null) {
return;
}
collection.iterator().hasNext();
}
回答by Bozho
org.hibernate.Hibernate.isInitialized(..)
There is no standard JPA solution to my knowledge. But if you want to actually initialize collections, you can create an utility method and iterate them (only one iteration is enough).
据我所知,没有标准的 JPA 解决方案。但是如果你想真正初始化集合,你可以创建一个实用方法并迭代它们(只需一次迭代就足够了)。
回答by robertgoko
As the other poster indicates, Hibernate has a method for this. However, there is no solution for this in pure JPA.
正如另一张海报所示,Hibernate 有一个方法。但是,在纯 JPA 中没有解决方案。
回答by amax
For eclipselink
, users cast the collection you are trying to access to an org.eclipse.persistence.indirection.IndirectList
, and then call its isInstantiated()
method. The following link has more information:
对于eclipselink
,用户将您尝试访问的集合强制转换为org.eclipse.persistence.indirection.IndirectList
,然后调用其isInstantiated()
方法。以下链接有更多信息: