19
votes

I tried to implement simple one-to-many association. after inspecting the item object with debugging mode, I found that List<Bid> bids already loaded. But List<Bid> bids property is annotated with FetchType.LAZY. some books and web pages claim that FetchType.LAZY is a hint JPA providers accept or reject. But I wonder on what condition JPA providers ignore FetchType.LAZY. Thank you in advance.

@Entity
@Table(name = "ITEM")
public class Item implements Serializable {

    @Id
    private Long id = null;

    private String name;
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "SELLER_ID", nullable = false)
    private User seller;

    @OneToMany(mappedBy = "item", fetch = FetchType.LAZY)
    private List<Bid> bids;

    /**
     * No-arg constructor for JavaBean tools.
     */
    public Item() {}

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public User getSeller() {
        return seller;
    }

    public void setSeller(User seller) {
        this.seller = seller;
    }

    @Override
    public String toString() {
        return "Item{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", seller=" + seller +
                ", bids=" + bids +
                '}';
    }
}
@Entity
@Table(name = "BID")
public class Bid implements Serializable {

    @Id @GeneratedValue
    @Column(name = "BID_ID")
    private Long id = null;

    @ManyToOne
    @JoinColumn(name = "ITEM_ID", nullable = false, updatable = false, insertable = false)
    private Item item;

    @ManyToOne
    @JoinColumn(name = "BIDDER_ID", nullable = false, updatable = false)
    private User bidder;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Item getItem() {
        return item;
    }

    public void setItem(Item item) {
        this.item = item;
    }

    public User getBidder() {
        return bidder;
    }

    public void setBidder(User bidder) {
        this.bidder = bidder;
    }

    @Override
    public String toString() {
        return "Bid{" +
                "id=" + id +
                ", bidder=" + bidder +
                '}';
    }
}
private static void itemSeller(EntityManager em) {

    Item item = em.find(Item.class, 1L);
    System.out.println("hello");

}

EDIT : I put break point at the statement System.out.println("hello"). I inspected the item object. See the picture : enter image description here

2
How do you determine that it's loaded eagerly? What's your test?JB Nizet
1-N has a DEFAULT of LAZY so specifying it is pointless. What the provider does is specific to your JPA provider (there is no "claim" that it is a hint only ... that is in the JPA spec). The provider I use (DataNucleus) respects what I tell it to use, always. Yours maybe thinks it know better than you? Does it know better than you?Neil Stockton
@NeilStockton Hibernate does of course support lazy loading. And yes, the JPA spec does say that: docs.oracle.com/javaee/7/api/javax/persistence/….JB Nizet
By inspecting the object i your debugger, you're asking it to call methods of the list to display its size, content, etc. And that of course initializes the list, lazily. Same for your toString() method, which implicitely loops through the list to print it.JB Nizet

2 Answers

30
votes

By inspecting the object in your debugger, you're asking it to call methods of the list to display its size, content, etc. And that of course initializes the list, lazily.

Same for your toString() method, which implicitely loops through the list to print it.

-1
votes

As Hibernate docs @OneToMany--default fetchType is LAZY @ManyToOne--default fetchType is EAGER.

If you want to change then fetch=fetchType.LAZY/EAGER

Basically, There are two times of hibernate object 1)Entity Object 2)Valued Object.So in your case Item have a to-many relationship with Bid, If you retrieve Item class at that time hibernate will not fetch related Bid Class record because you did fetch type is LAZY, But you fetch Bid Class record hibernate fetch related Item eagerly for you, because Bid has a ManyToOne relationship with Item class and default fetch type for ManyToOne is EAGER.