简体   繁体   中英

Why Lazy Fetching is not working JPA

i have a hard time understanding the lazy fetching since i does not work for as i read about it in a book, they say that in lazy fetching jpa will load the entities only when they are accessed through geters so i created an Arquillian project to test this concept but it does not work. here are my two entities

Person

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 
}

Address

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

I have a stateless session bean with this method

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

since i detached the entity before accessing the address the addresses list should be empty and when i hace detached it so it is no longer managed by the entitymanager so i should not get addresses for the person the problem is that i can fetch the addresses of that person even i have lazy fetch for addresses field and detached the entity before accessinbg the addresses field!!!! pleas some have the explanation .

An other test

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

Yeah buddy, you were right. You are not doing anything wrong here. I just opened the Pro JPA 2, 2nd edition Book and found this :

这是快照

You are using glassfish-embedded which is actually causing the problem. Your code have no problem. As mentioned by the author of the above mentioned book,

Some vendors might attempt to resolve the relationship, while others might simply throw an exception or leave the attribute uninitialized.

So, in your case, the relationship is resolved rather than lazy loading. Just Implement the same example using other vendor and you will not face any problem. Here using glassfish-embedded, lazyfetch is not working. Otherwise the exception should be thrown, as the variable p is detached.

Here is the link where i also read this beautiful piece of information

Here is the snapshot from above link 快照

You are only detaching the parent entity, Person. You are not detaching the children entities, Addresses, and when you get addresses, it refers to entities which are still managed by the persistence context.

If you want the children to be detached as well, you should use CascadeType.DETACH.

You might say, "But my FetchType is set to LAZY!". Just because it's LAZY, doesn't mean the object is null. Hibernate returns Proxy objects for collection types, and once you try to access them, it will populate their values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM