【问题标题】:Spring Data JPA loads one to one relationship in two queriesSpring Data JPA 在两个查询中加载一对一的关系
【发布时间】:2018-01-10 21:23:04
【问题描述】:

我有以下课程:

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

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

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=?

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

更新 我正在使用 CrudRepositor:

public interface UserIdentityRepository extends CrudRepository<UserIdentity, Long> {
  UserIdentity findByFacebookId(String facebookId);
  UserIdentity findByPhoneNumber(String phoneNumber);
}

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

【问题讨论】:

    标签: java spring hibernate spring-data-jpa


    【解决方案1】:

    您在实体上指定的 FetchType 仅在使用 EntityManager 上不接受任何类型查询的方法时使用。 这就是您在调用findById() 时所做的有效工作。

    但是,如果您在使用 findByPhoneNumber() 的查询方法时像 Spring Data 一样为您指定查询,则该查询用于确定获取策略。

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

    我已经准备好了a simple example over at Github

    我用的是平凡的实体图

    @NamedEntityGraph(name = "joined", includeAllAttributes = true)
    

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

    【讨论】:

    • 我试过你的方法,它解决了角色问题。但是我遇到了新的权限问题,因为我与角色有多对多的关系。
    • 您可以调整 EntityGraph 以指定所需的获取策略。如果这对您不起作用,那将是一个很好的新问题。
    【解决方案2】:

    拥有一个查询的唯一方法..在您的情况下它只会加载 UserIdentity 是将关系设置为 LAZY:

    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @Fetch(FetchMode.JOIN)
    @JoinColumn(name = "role_id")
    private Role role;
    

    然后在事务方法中首次使用时加载它。

    如果它符合您的逻辑设计,您可以将 Role.id 作为主键和外键并使用@MapsId,如本文所述:link

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-14
      • 1970-01-01
      • 2019-01-15
      • 1970-01-01
      • 1970-01-01
      • 2017-08-19
      • 2021-03-16
      • 1970-01-01
      相关资源
      最近更新 更多