【问题标题】:JPA Collection of objects with Lazy loaded field具有延迟加载字段的对象的 JPA 集合
【发布时间】:2016-08-24 05:57:44
【问题描述】:

在每个集合对象中强制初始化延迟加载字段的好方法是什么?

此时我唯一想到的是使用for each 循环来迭代槽收集并调用该字段的getter,但这不是很有效。集合甚至可以有 1k 个对象,在这种情况下,每次迭代都会触发到 db。

我无法更改从数据库中获取对象的方式。

代码示例。

public class TransactionData{

@ManyToOne(fetch = FetchType.LAZY)
private CustomerData customer;
...
}

List<TransactionData> transactions = getTransactions();

【问题讨论】:

    标签: java jpa


    【解决方案1】:

    您可以定义实体图来否决默认提取类型,因为它们是在映射中定义的。

    请看下面的例子

    @Entity
    @NamedEntityGraph(
        name = "Person.addresses", 
        attributeNodes = @NamedAttributeNode("addresses")
    )
    public class Person {
        ...
        @OneToMany(fetch = FetchType.LAZY) // default fetch type
        private List<Address> addresses;
        ...
    }
    

    在以下查询中,地址现在将被急切地加载。

    EntityGraph entityGraph = entityManager.getEntityGraph("Person.addresses");
    TypedQuery<Person> query = entityManager.createNamedQuery("Person.findAll", Person.class);
    query.setHint("javax.persistence.loadgraph", entityGraph);
    List<Person> persons = query.getResultList();
    

    通过这种方式,您可以为每个不同的用例定义特定的获取行为。

    另请参阅:

    顺便说一句:即使您将映射定义为惰性,大多数 JPA 提供程序都会执行 @XXXtoOne 关系的预加载。 JPA 规范确实允许这种行为,因为延迟加载始终只是暗示数据可能会或可能不会立即加载。另一方面,急切加载必须立即执行。

    【讨论】:

    • 感谢您的回复,很遗憾,我既不能使用动态实体图也不能使用命名实体图,因为这会阻止我使用在这种情况下从数据库中获取数据所必需的搜索条件。
    • 您在问题中没有提到类似的内容。如果这不能回答您的问题,请澄清您最初的问题。除此之外,我不同意您的评论:您可以在查询中定义参数和/或您甚至可以将实体图与 Criteria API 一起使用
    【解决方案2】:

    你可以这样做:

    //lazily loaded
    List<Child> childList = parent.getChild(); 
    
    // this will get all the child in memory of that particular Parent
    Integer childListSize = childList.size();
    

    但是,如果您急切加载,则将为每个父母加载所有孩子。这应该是你最好的选择。

    【讨论】:

    • 我不确定这是否是一个好的解决方案,我只有父母对象的集合。
    猜你喜欢
    • 2016-12-21
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多