3

我有以下两个实体:

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;
}

SQL 是:

CREATE TABLE USER (
ID BIGINT NOT NULL, 
EMAIL VARCHAR(255) UNIQUE, 
PASSWORD VARCHAR(255), 
PRIMARY KEY (ID)
)
CREATE TABLE ROLE (
ID BIGINT NOT NULL, 
EMAIL VARCHAR(255),
ROLE VARCHAR(255), 
USER_ID BIGINT, 
PRIMARY KEY (ID),
FOREIGN KEY (USER_ID) REFERENCES USER(ID)
)

以下 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)

4

1 回答 1

2

有多种方法可以告诉你应该如何加载另一个和一个关系。一个是在查询级别,使用 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;
}

当您加载角色时,您还可以在没有任何特殊注释或加入查询的情况下获得用户的原因是 JPA 中的 ManyToOne 关系默认具有 fetch=EAGER :

http://docs.oracle.com/javaee/5/api/javax/persistence/ManyToOne.html#fetch ()

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

http://docs.oracle.com/javaee/5/api/javax/persistence/OneToMany.html#fetch ()

于 2012-08-21T21:44:03.897 回答