【发布时间】:2021-06-02 14:20:34
【问题描述】:
考虑以下实体:
用户实体:
@Entity(name = "user")
public class UserEntity {
@Id
@Column(name = "id", columnDefinition = "serial")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@OneToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
private List<RoleEntity> roles = new ArrayList<>();
}
角色实体:
@Entity(name = "role")
@NamedEntityGraph(
name = "role.entity_graph",
attributeNodes = {
@NamedAttributeNode(value = "permissions")
})
public class RoleEntity {
@Id
@Column(name = "id", columnDefinition = "serial")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "role_permission", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id"))
private List<PermissionEntity> permissions = new ArrayList<>();
}
权限实体:
@Entity(name = "permission")
public class PermissionEntity {
@Id
@Column(name = "id", columnDefinition = "serial")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
}
UserEntity 中的roles 应该是惰性的。问题是当使用roles(调用getter)时,hibernate会通过查询每个角色和查询每个角色的每个权限来获取它们,从而导致n+1问题。
因此我的问题是:我怎样才能通过一个查询延迟获取用户角色?我可以以某种方式利用RoleEntity 的EntityGraph 吗?
注意:我已经尝试过使用@Fetch:
@Fetch(FetchMode.JOIN)
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "role_permission", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id"))
private List<PermissionEntity> permissions = new ArrayList<>();
这不起作用。然而,与@BatchSize 一起使用时,它可以正常工作。
@Fetch(FetchMode.JOIN)
@BatchSize(size = 1000)
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "role_permission", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id"))
private List<PermissionEntity> permissions = new ArrayList<>();
不过,我对这个解决方案并不满意。为什么要加@BatchSize?
【问题讨论】:
标签: java performance hibernate jpa spring-data-jpa