【问题标题】:JPA Hibernate Lazy Fetch Attributes with one QueryJPA Hibernate Lazy Fetch Attributes with a Query
【发布时间】: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


    【解决方案1】:

    我认为使用子图可能会对您有所帮助。看看他网站上Thorben Janssen 的描述:Entitygraph with multiple Subgraphs,引用:

    @NamedEntityGraph(
        name = "graph.AuthorBooksPublisherEmployee", 
        attributeNodes = @NamedAttributeNode(value = "books", subgraph = "subgraph.book"), 
        subgraphs = {
            @NamedSubgraph(name = "subgraph.book", 
                           attributeNodes = @NamedAttributeNode(value = "publisher", subgraph = "subgraph.publisher")),
            @NamedSubgraph(name = "subgraph.publisher", 
                           attributeNodes = @NamedAttributeNode(value = "employees")) })
    

    【讨论】:

      猜你喜欢
      • 2017-08-21
      • 2015-05-08
      • 1970-01-01
      • 1970-01-01
      • 2019-05-17
      • 2017-04-11
      • 2011-02-10
      • 2016-12-22
      • 2018-12-09
      相关资源
      最近更新 更多