当前位置: 首页 > 知识库问答 >
问题:

JPA Hibernate惰性获取属性和一个查询

昝涛
2023-03-14

考虑以下实体:

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


}

用户实体角色应该被延迟获取。问题是,当使用角色时(调用getter),hibernate会通过对每个角色的查询和对每个角色的每个权限的查询来获取它们,从而导致n1问题。

因此,我的问题是:如何通过一个查询获取用户角色?我可以利用角色属性的实体图吗?

注意:我已经试过使用@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


共有1个答案

太叔望
2023-03-14

我认为使用子图可能会对您有所帮助。看看Thorben Janssen在他的网站上的描述:具有多个子图的实体图,引用:

@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")) })
 类似资料:
  • 问题内容: 有没有一种方法来获取JSON对象的第一个属性的名称? 我想做这样的事情: 编辑: 我得到一个JSON对象,其中包含具有图像URL的数组类别。 像这样: 然后,我遍历该对象以插入图像,而我真正想要的只是一种优雅的方式来查看首先插入哪个类别。一开始我只是做了 但这有点丑陋…所以基本上这只是一个优雅的问题:p 问题答案: 不能 保证 对象属性的顺序与您放置它们的方式相同。但是,实际上,所有主

  • 问题内容: 有什么方法可以在Grails / Gorm中使用懒惰属性获取?像这样 @Basic(提取= FetchType.LAZY) 注释(它也适用于左连接获取吗?) (例如,延迟加载String属性) 问题答案: 这个问题被问Grails的用户邮件列表在这里。讨论了几个不同的选项。

  • 问题内容: 我正在尝试从解码为PHP对象的JSON数据中获取一个属性。这只是一个YouTube数据API请求,它返回具有内容对象的视频对象。 在做 抛出“意外的T_DNUMBER”-这很合理。但是,如何获得数字属性的值? 我确定我应该知道这一点。提前致谢。 问题答案: 这应该工作:

  • 通过这个简单的类,我得到了编译器警告 尝试在其自己的 setter/getter 中修改/访问 当我这样使用它时: 我得到一个EXC坏访问。如果没有明确的支持ivars,我该如何做呢?

  • 问题内容: 我使用Hibernate 5.2.5(如果重要的话,也可以使用kotlin和spring 4.3.5),并且我希望延迟加载类的某些字段。但是问题是所有字段都立即加载,我没有任何特殊的Hibernate设置,也没有使用Hibernate.initialize()。 这就是我的查询方式 TaskRepoImpl: TaskService: 并输出: 请告知我的代码出了什么问题以及如何使Hi

  • 我的理解是,默认情况下,Hibernate将所有关系类型的FetchType设置为lazy。 在我的例子中,我有一个双向的OneToMany-ManyToOne关系,如下所示: 另一个问题是我如何得到一个有特定名字的孩子?是否可以通过存储库进行操作?还是需要getChildren(parentId)并迭代直到找到以特定方式命名的那个? 编辑:在一些建议之后,我继续这样实现了我的ChildRepos