[英]Spring Data JPA loads one to one relationship in two queries
我有以下课程:
@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(),则它将不起作用。
您在实体上指定的FetchType
仅在EntityManager
上使用不接受任何类型查询的方法时使用。 这是您在调用findById()
时有效执行的操作。
但是,如果在使用查询方法作为findByPhoneNumber()
时像Spring Data那样为您指定查询,则该查询将用于确定获取策略。
但是您可以通过指定实体图来控制它。 您将在实体类中添加@NamedEntityGraph
批注。 还有一个@EntityGraph
注释,用于引用该命名实体图的查询方法。
我用了琐碎的实体图
@NamedEntityGraph(name = "joined", includeAllAttributes = true)
它会急切地获取所有内容,而这实际上可能就是您想要的。
进行一个查询的唯一方法..并且仅在您的情况下加载UserIdentity
是将关系设置为LAZY:
@OneToOne(fetch = FetchType.LAZY, optional = false)
@Fetch(FetchMode.JOIN)
@JoinColumn(name = "role_id")
private Role role;
然后在首次使用时以事务方法加载它。
如果符合您的逻辑设计,则可以将Role.id用作主键,也可以将其作为外键,并使用@MapsId
,如本文所述: link
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.