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关系,您必须做一些额外的工作。