JPA:自动加载子对象不会';I don’我没有按预期工作

JPA:自动加载子对象不会';I don’我没有按预期工作,jpa,persistence,jpa-2.0,eclipselink,Jpa,Persistence,Jpa 2.0,Eclipselink,我有以下两个实体: class Role { @Id Long id; @Column String email; String role; @ManyToOne User user; } class User { @Id Long id; @Column(unique=true) String email; String password; @OneToMany(mappedBy = "user") @OrderBy("role asc") List

我有以下两个实体:

class Role {
  @Id Long id;
  @Column String email;
  String role;
  @ManyToOne User user;
}

class User {
  @Id Long id;
  @Column(unique=true) String email;
  String password;

  @OneToMany(mappedBy = "user")
  @OrderBy("role asc")
  List<Role> roles;
}
下面的JUnit在最后一行的第二行失败。我从子系统自动加载了用户(父系统),但没有从父系统自动加载子系统。我做错了什么

    Role r = em.createQuery("select r from Role r where r.email = :email", Role.class)
            .setParameter("email", "john@google.com")
            .getSingleResult();
    assertEquals("registered", r.role());
    assertEquals("john@google.com", r.user().email());

    User u = em.createQuery("select u from User u where u.email = :email", User.class)
            .setParameter("email", "john@google.com")
            .getSingleResult();

    assertEquals("john@google.com", u.email());
    assertEquals("asdf", u.password());

    assertEquals(1, u.roles().size()); FAILS HERE!!!
    assertEquals("registered", u.roles().get(0).role());

我使用的是EclipseLink 2.3.2(JPA)

有多种方法可以告诉您如何加载关系的另一个和。一个是在查询级别,使用fetch join,类似于以下内容:

select u from User u left join FETCH u.roles r where...
class User {
  @Id Long id;
  @Column(unique=true) String email;
  String password;

  @OneToMany(mappedBy = "user", fetch=FetchType.EAGER)
  @OrderBy("role asc")
  List<Role> roles;
}
另一个是在关系声明级别,类似这样:

select u from User u left join FETCH u.roles r where...
class User {
  @Id Long id;
  @Column(unique=true) String email;
  String password;

  @OneToMany(mappedBy = "user", fetch=FetchType.EAGER)
  @OrderBy("role asc")
  List<Role> roles;
}
类用户{
@Id长Id;
@列(unique=true)字符串电子邮件;
字符串密码;
@OneToMany(mappedBy=“user”,fetch=FetchType.EAGER)
@订购人(“角色asc”)
列出角色;
}
加载角色时,在查询中也会获得用户,而无需任何特殊注释或联接,这是因为JPA中的许多同一关系在默认情况下都具有fetch=EAGER:

()

默认情况下,一对多具有fetch=lazy:


()

如果我将角色修改为同时具有FetchType.EAGER,则没有区别。照我的理解,以及它使用Hibernate的方式,LAZY只是意味着在调用getRoles方法之前,不会执行获取子对象的SQL。代理截取该方法调用并执行SQL,并将数据注入返回的集合。没有?是的,差不多就是这样。诀窍在于代理(实际上是Hibernate/JPA包装器)只有在用于获取它的会话仍然打开时才能执行此操作。如果没有,您将得到可怕的惰性初始化异常。更不用说使用延迟抓取是n+1选择的一个经典示例(为每个懒散初始化的关系进行选择)。如果你问我,最好的办法是在查询时急切地获取你需要的所有数据。我可能在这里遗漏了一些东西,但在我看来,你有一个可以加载的多人关系和一个不能动态加载的单人关系,默认配置。根据文档,这几乎就是他们应该采取的行动。为了让您的JUnit测试通过,即在获取根时加载OneToMany关系,您必须做一些额外的工作。