Spring Data JPA 在两个查询中加载一对一关系

Ale*_*lex 5 java spring hibernate spring-data-jpa

我有以下课程:

@Data
@Entity
@Table(name = "user_info")
public class UserIdentity implements UserDetails {
  @Id
  private Long id;
  private String username;
  private String password;
  private String facebookId;
  private String phoneNumber;
  private Timestamp unblockDate;
  @OneToOne(fetch = FetchType.EAGER, optional = false)
  @Fetch(FetchMode.JOIN)
  @JoinColumn(name = "role_id")
  private Role role;

  }

@Data
@Entity
@Table(name = "role")
public class Role {
  @Id
  private Long id;
  private String name;
  @ManyToMany
  @Fetch(FetchMode.JOIN)
  @JoinTable(name = "role_permission", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id"))
  private List<Permission> permissions;
}

@Data
@Entity
@Table(name = "permission")
public class Permission {
  @Id
  private Long id;
  private String name;
}
Run Code Online (Sandbox Code Playgroud)

当我查询用户身份时,我可以看到日志中生成了这两个查询:

Hibernate: select useridenti0_.id as id1_3_, useridenti0_.facebook_id as facebook2_3_, useridenti0_.password as password3_3_, useridenti0_.phone_number as phone_nu4_3_, useridenti0_.role_id as role_id7_3_, useridenti0_.unblock_date as unblock_5_3_, useridenti0_.username as username6_3_ from user_info useridenti0_ where useridenti0_.facebook_id=?
Hibernate: select role0_.id as id1_1_0_, role0_.name as name2_1_0_, permission1_.role_id as role_id1_2_1_, permission2_.id as permissi2_2_1_, permission2_.id as id1_0_2_, permission2_.name as name2_0_2_ from role role0_ left outer join role_permission permission1_ on role0_.id=permission1_.role_id left outer join permission permission2_ on permission1_.permission_id=permission2_.id where role0_.id=?
Run Code Online (Sandbox Code Playgroud)

但我预计只会看到一个查询。你能帮我找出我做错了什么吗?

更新 我正在使用 CrudRepositor:

Hibernate: select useridenti0_.id as id1_3_, useridenti0_.facebook_id as facebook2_3_, useridenti0_.password as password3_3_, useridenti0_.phone_number as phone_nu4_3_, useridenti0_.role_id as role_id7_3_, useridenti0_.unblock_date as unblock_5_3_, useridenti0_.username as username6_3_ from user_info useridenti0_ where useridenti0_.facebook_id=?
Hibernate: select role0_.id as id1_1_0_, role0_.name as name2_1_0_, permission1_.role_id as role_id1_2_1_, permission2_.id as permissi2_2_1_, permission2_.id as id1_0_2_, permission2_.name as name2_0_2_ from role role0_ left outer join role_permission permission1_ on role0_.id=permission1_.role_id left outer join permission permission2_ on permission1_.permission_id=permission2_.id where role0_.id=?
Run Code Online (Sandbox Code Playgroud)

我注意到以下事情 - 如果我使用findById()方法进行搜索,它会按预期工作,但如果我使用findByPhoneNumber(),那么它就不起作用。

Jen*_*der 5

FetchType在实体上指定的仅在使用不EntityManager采用任何类型查询的方法时使用。这就是您在调用 时实际上正在做的事情findById()

但是,如果您像 Spring Data 那样指定查询,那么当您使用查询方法时,findByPhoneNumber()该查询将用于确定获取策略。

但您可以通过指定实体图来控制它。您可以@NamedEntityGraph向实体类添加注释。以及@EntityGraph引用该命名实体图的查询方法的注释。

我在 Github 上准备了一个简单的例子

我使用了简单的实体图

@NamedEntityGraph(name = "joined", includeAllAttributes = true)
Run Code Online (Sandbox Code Playgroud)

它急切地获取所有内容,这实际上可能就是您想要的。