【问题标题】:Why Lazy Fetching is not working JPA为什么 Lazy Fetching 不起作用 JPA
【发布时间】:2017-02-19 14:38:03
【问题描述】:

我很难理解延迟获取,因为我在书中读到它时并不工作,他们说在延迟获取中,jpa 只有在通过 geters 访问实体时才会加载实体,所以我创建了一个 Arquillian项目来测试这个概念,但它不起作用。 这是我的两个实体

人物

package com.actionbazaar.model;

@Entity
@TableGenerator(
        initialValue = 5,
        name = "PERSON_SEQ",
        table = "PERSON_SEQ_TABLE",
        pkColumnName = "SEQ_NAME",
        pkColumnValue = "PERSON",
        valueColumnName = "SEQ_VALUE")
public class Person implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String fname;
    private String lname;
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "owner", cascade = CascadeType.PERSIST)
    List<Address> addresses;
    //getters and setters 
}

地址

    @Entity
public class Address implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String city;
    private String zip;
    private String street;

    @ManyToOne
    private Person owner;
//getters and setters
}

我有一个使用这种方法的无状态会话 bean

    public Person getFirstPerson() {
    Person p = em.find(Person.class, 1);
    em.detach(p);
    //why this call does not create an exception
    p.getAddresses().get(0);
    return p;
}

因为我在访问地址之前分离了实体,所以地址列表应该是空的,当我分离它时,它不再由 entitymanager 管理,所以我不应该为这个人获取地址 问题是我可以获取那个人的地址,即使我有地址字段的延迟获取并在访问地址字段之前分离实体!!!! 请一些人解释一下。

另一个测试

Person p= myStatlessSessionBean.getFirstPerson();
myOtherStalessSesionBean.moveAllPeopleToCity("NY");
if(p.getAddresses().get(0).getCity().equals("NY"))
{
  system.out.prinln("person moved");
}
else {
system.out.prinln("person did not move");
} //prompts person did not move

【问题讨论】:

    标签: java hibernate jpa jboss-arquillian glassfish-embedded


    【解决方案1】:

    是的,伙计,你是对的。你在这里没有做错任何事。我刚刚打开 Pro JPA 2, 2nd edition Book 发现了这个:

    您正在使用 glassfish-embedded,这实际上是导致问题的原因。你的代码没有问题。正如上述书的作者所说,

    一些供应商可能 尝试解决关系,而其他人可能只是抛出异常或使属性未初始化。

    因此,在您的情况下,关系已解决,而不是延迟加载。只需使用其他供应商实施相同的示例,您就不会遇到任何问题。这里使用 glassfish-embedded,lazyfetch 不起作用。否则应该抛出异常,因为变量p 已分离。

    这是link,我也在这里读到了这条美丽的信息

    这是上面链接的快照

    【讨论】:

    • 是的..你是对的..我很想知道为什么会发生这件事。获得更多信息。谢谢@achabahe
    • @achabahe 我怀疑这就是原因,但是您用“休眠”标记了您的问题,尽管您似乎没有使用它。这是误导。
    • 可能是他试图达到冬眠认识的人:D? @JBNizet ^_^
    【解决方案2】:

    您只是分离父实体 Person。您没有分离子实体,地址,当您获得地址时,它指的是仍然由持久性上下文管理的实体。

    如果您也希望子项也被分离,则应使用 CascadeType.DETACH。

    您可能会说,“但是我的 FetchType 设置为 LAZY!”。仅仅因为它是 LAZY,并不意味着该对象为空。 Hibernate 为集合类型返回 Proxy 对象,一旦你尝试访问它们,它就会填充它们的值。

    【讨论】:

    • 第二个测试怎么样!,我已经更改了级联以添加 CascadeType.DETACH,但仍然是同样的问题,首先我想知道是否正确理解了我期望的概念和行为对的一个
    • 我同意@Tahir。根据 JPA 规范:“当需要跨供应商的互操作性时,应用程序不得使用延迟加载。” JPA 规范还提到 LAZY fetch 只是一个提示,它告诉我它的实现留给了供应商。
    猜你喜欢
    • 1970-01-01
    • 2018-06-07
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多