2014-01-31 49 views
0

美好的一天。我需要检查字段的初始化(加载)。对于此任务,我尝试使用Hibernate.isInitialized。我有以下实体:懒惰加载字段休眠“isInitialized”

@Entity 
public class Contractor { 
    /* ... */ 

    @OneToMany(mappedBy = "contractor", fetch = FetchType.LAZY) 
    private List<Work> works = new ArrayList<Work>(); 

    /* ... */ 
} 

@Entity 
public class Work { 
    /* ... */ 

    @ManyToOne(fetch = FetchType.LAZY) 
    private Contractor contractor; 

    @ManyToOne(fetch = FetchType.LAZY) 
    private Project project; 

    /* ... */ 
} 

@Entity 
public class Project { 
    /* ... */ 

    @OneToMany(mappedBy = "project", fetch = FetchType.LAZY) 
    private List<Work> works = new ArrayList<Work>(); 

    /* ... */ 
} 

然后我试图通过如下方法获取实体:

List<Contractor> list = em.createQuery("SELECT c FROM Contractor c").getResultList(); 
    for (Contractor contractor : list) { 
     Hibernate.initialize(contractor.getComments()); 
     Hibernate.initialize(contractor.getWorks()); 
     for (Work work : contractor.getWorks()) { 
      Hibernate.initialize(work.getProject()); 
     } 
    } 
return list; 

之后,我通过双向查询(序列化)领域的初始化标志:

Project p = contractor.getWorks().get(0).getProject(); 
Field f = Hibernate.getClass(p).getDeclaredField("works"); 
f.setAccessible(true); 
System.out.println(Hibernate.isInitialized(f.get(p))); 

System.out.println(Hibernate.isInitialized(contractor.getWorks().get(0).getProject().getWorks())); 

结果对于集合(true,false)是不同的,但对于单个对象是相同的。可能有人知道为什么?

回答

0

你可以保证你懒的关系在查询本身取出,并避免检查,如果它们被初始化:

SELECT c FROM Contractor c JOIN FETCH c.comments JOIN FETCH c.works 

的连接抓取是一种特殊类型的联接它只是确保相关实体的负载。这仍然只是返回承包商对象,但它会确保其相关的评论和作品已被加载(即使它们被宣布为懒惰)。

- 编辑 -

也许你可以使用标准的JPA API做验证。两者PersistenceUnitUtils类和PersistenceUtil有两种有用的方法:

boolean isLoaded(java.lang.Object entity) 

哪个确定属于持久性单元的实体的负载状态。

boolean isLoaded(java.lang.Object entity, java.lang.String attributeName) 

它确定属于持久性单元的实体的给定持久属性的加载状态。

这些太方法应该为你做的伎俩,希望以一致的方式。

+0

是的。我使用JOIN FECT,但不是全部选择。但我尝试编写通用的序列化方法(对于未加载的惰性字段并且已经通过JOIN FECT惰性字段加载,所以我需要一种方法来动态检查初始化。 – dmitrievanthony

+0

@dmitrievanthony我编辑了我的回答,提供了使用“PersistenceUnitUtil”或'PersistenceUtil'类。虽然看起来你的问题更多的是为什么休眠行为在这种情况下是奇怪的,你描述(我不知道)。 –

+0

是的,我尝试使用PersistenceUtil,但结果相同 – dmitrievanthony

0

Hibernate persisting ArrayList - Issues

我也有类似的问题。需要标注我的课

@OneToMany(mappedBy="tournament") 
private List<String> registered; 

改变这种

@ElementCollection 
@CollectionTable (name = "tournament_eligible", [email protected](name="id")) 
private List<String> username; // Contains a list of eligible members 

这解决这个问题对我来说,虽然我的名单刚刚在他们String对象,我无法想象这将是太多不同。

+0

不幸的是,我不能使用像String这样的简单类型,我的理解是,这种方法不适用于Entities? – dmitrievanthony

+0

我不确定。我还没有尝试过与实体。我猜想它应该起作用,因为注释是指集合而不是实体。它不应该在收集什么。但那只是我猜测。 –

+1

不是“相似”。你有一个非实体集合,JPA规范和我见过的所有文档(JPA2)都说使用ElementCollection。 OP有一个实体集合,并且所有文档都需要OneToMany(就像现在这样)。因此,这只是一个分心 –