Hibernate fetchtype Understanding

Source: Internet
Author: User

JPA defines the relationships between entities in the following ways:
@OneToOne
@ManyToOne
@OneToMany
@ManyToMany
When defining them, you can specify the loading mode by using the Fetch property, which has two values:
Fetchtype.lazy: Lazy Loading
Fetchtype.eager: Urgent loading
An urgent load is good to understand that when loading an entity, the attribute (property) and fields (field) are immediately loaded from theDatabaseLoaded in
The most common problems encountered during development are lazy loading, and the problem is one:
"Why do I define deferred loading, but it doesn't work, and the related properties or fields will be loaded immediately?" ”
To this question, my understanding is that we first assume the following relationship:
@Entity
@Table (name = "Orders")
Class order{

@OneToMany (cascade = {Cascadetype.merge,cascadetype.persist,cascadetype.refresh},fetch = Fetchtype.lazy,mappedby = " Order ")
Private Collection
LineItems = new HashSet
();

@OneToOne (cascade={cascadetype.remove},fetch=fetchtype.lazy,mappedby= "order")
@JoinColumn (name= "order_id")
Private Orderprice Saleprice;

@OneToOne (Cascade={cascadetype.remove},fetch=fetchtype.lazy)
@JoinColumn (name= "customer_id")
Private customer customer;
}

@Entity
@Table (name = "Order_items")
Class lineitem{

@ManyToOne (cascade = {Cascadetype.merge, cascadetype.persist,
Cascadetype.refresh},fetch = Fetchtype.lazy)
@JoinColumn (name = "order_id", referencedcolumnname = "order_id")
private order order;

}

@Entity
@Table (name = "Order_finance")
@AttributeOverride (name= "id", [email protected] (name= "order_id"))
Class Orderprice extends price{

private order order;

@OneToOne (Cascade={},fetch=fetchtype.lazy)
@JoinColumn (name= "order_id", Referencedcolumnname= "order_id")
Public Order GetOrder () {
return order;
}

public void Setorder (order order) {
This.order = order;
}

}

@MappedSupperclass
@Table (name = "Order_finance")
Class price{
@Id
Public Integer getId () {
...
}
}
The table relationship is: The Orders table is a separate table, the Order_items table has a foreign key (order_id) referenced to the Orders table, and Order_finance has a foreign key (order_id) referenced to the Orders table.
Order_items ——->orders< ———— order_finance
|
Customer
Now the question is:
Order.lineitems This @onetomany lazy delay load is working, find does not find out when the order LineItems
Order.customer This @onetomany lazy delay load is working, and find does not find out when the order is out of customer
Order.saleprice This @onetoone lazy delay load does not work, find order will be the relevant Orderprice also fetch out
Lineitem.order This @manytoone lazy delay load is working, find LineItem did not put the relevant order find out
Orderprice.order This @onetoone lazy delay load does not work, find orderprice when the relevant order find out
Lazy loading, as the name implies, is to be loaded from the database when the specific property is accessed, such as in an example, the order should be loaded only when the Orderprice.getorder () is called, and the order should not be loaded when the Orderprice is loaded.
So first think about how hibernate knows when to invoke the Get method of a related entity for lazy loading.
The answer is that it does not know that hibernate does not know when to invoke the relevant get method, so how does hibernate implement only the access to load this point?
Hibernate uses proxies, and calls to entities are accepted and processed by the agent, and hibernate can set the time at which the agent is called to load the data for lazy loading. Then for a mapped object, either it has a value, or it is null, it is not very useful to establish a proxy for null values, and you cannot establish a dynamic proxy for null. That is, hibernate should consider whether this mapped object is null when establishing a proxy for lazy loading. If NULL does not need to establish a proxy, directly sets the value of the map to NULL, if the mapped object is not NULL, then hibernate establishes the proxy object
Delayed load failure is caused by determining whether the contents of the map are null
First look at @onetomany, such as the example of Order.lineitems, which is a collection,hibernate loading the order without loading lineitems, Instead, create a proxy that is a proxy for collection (typically Org.hibernate.collection.persistentBag). Unless you call a Order.getLineItems.size () or Order.getLineItems.get () method, hibernate will load the order's lineitems data, or else just call Order.getlineitems is not loaded into the data, because this time there is no specific access to the LineItem.
Since the proxy is built for collection and not for the entity, Hibernate does not have to think too much about whether it is null, and if LineItem does not, it simply means that the set is 0, and this collection is not null. So it's easy to implement lazy loading
Now look at the example @onetoone Order.saleprice. Why would it fail?
Hibernate will also establish a proxy, but this agent is built for Orderprice (if the deferred load succeeds, this proxy class is like customer_javasisst_$1), the default optioanl=true, That is to say, Orderprice can be null, so hibernate has to consider, here is a null? Or put an agent. But in order this entity is not sure whether it has a price (but in the price to know his order, there is a foreign key point to order), so hibernate to confirm the existence of this orderprice, this confirmation caused by the delay load failure, Because the orderprice to be queried once, if there is no mapping value is NULL, if there is this time the value is taken out, of course, there is no proxy
Order.customer deferred loading is successful, the order table has a foreign key associated to the Customer table, and Hibernate should know from here that the customer does exist without setting the mapping value to NULL. Can be set as proxy class customer_javasisst_$2
So if you change the Order.saleprice mapping definition to:
@OneToOne (cascade={cascadetype.remove},fetch=fetchtype.lazy,optional=false,mappedby= "order")
@JoinColumn (name= "order_id")
Private Orderprice Saleprice;
Deferred loading succeeds, because optional=false specifies that Saleprice is not optional and must have a value, so hibernate does not have to consider whether to put the null or the proxy, since must have the value, but also delay loading, then set the proxy class
According to the above, Orderprice defines a foreign key associated to the order, and that orderprice.order this lazy load should be successful, but why does it fail?
is the order and Orderprice defined onetoone relationships on both sides?
In my case, this failed, I think, because orderprice the definition of this entity: @AttributeOverride (name= "id", [email protected] (name= "order_id"))
Take a look at Manytoone's lineitem.order, this delayed load is also successful. Because LineItem defines the external health related to order
For lazily loaded objects, if the container has been detached, the call gets Org.hibernate.LazyInitializationException:could not initialize Proxy–no Session method exception
There is also a case where lazy loading "doesn't seem to work": it actually works, but where the code might be called to the related get method to load the deferred object, so it seems to be unsuccessful
Summarize:
For lazy loading, hibernate does not know when to invoke the Get method of a deferred-loaded property/field, so for deferred-loaded properties/fields, Hibernate will wrap (Wrapper) by creating proxy proxies.
The agent may be established according to the entity itself, or it can be based on a set, if it is based on a set, lazy loading is generally successful, if it is established by the entity, NULL is unable to establish a proxy, if it can be determined that the proxy class must exist, the delay load can be successful, the related mappings are placed in the proxy class, If the mapped property is not determined to exist, then the query is made to the database, which causes the delay to fail.
A foreign key definition allows hibernate to know whether a mapped property exists
You can also tell hibernate by Optional=false that the mapped attribute must exist

Hibernate fetchtype Understanding

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.