Go NHibernate Tour (13): A preliminary study on the immediate loading mechanism

Source: Internet
Author: User

The content of this section

    • Introduced
    • Load now
    • Example analysis
      • 1. One-to-many relationship instances
      • 2. Many-to-many relationship instances
    • Conclusion
Introduced

We learned from the previous article that the default loading mechanism in NHibernate-lazy loading. The essence is the use of GoF23 in the proxy mode implementation, this section we simple analysis nhibernate another loading mechanism-load immediately. I use a picture image to show the immediate loading mechanism.

Load now

As the name implies, the collection of associated objects is immediately loaded, as opposed to lazy loading. There are three ways to load immediately, namely the optional lazy attribute, the utility class provided by NHibernate, and the HQL crawl strategy. The following example analyzes the mechanism in turn.

Example Analysis 1. One-to-many relationship instances

In a one-to-many relationship instance, we use the Customer object and the order object as an example, the previous method is still used in the data access layer, where the method of forcing the session is used, and why is the use forced to release the resource? I just want to use this to emulate the session mechanism in a Web application. It is more meaningful to use this analysis than to release resources without a using.

Methods in the data Access layer: Load the Customer object and use the using-force cleanup to close the session

Public Customer lazyloadusingsession (int customerId) {    using (isession _session = new SessionManager (). GetSession ())    {        return _session. Get<customer> (customerId);    }}
1. Use the lazy= "false" property

In the previous article we have not modified the mapping file is always the default is lazy= "true", nhibernate the default lazy loading.

The first method described here is to modify the mapping file to load immediately, open the Customer.hbm.xml file, and add lazy= "false" to the set element.

Write a test validation that invokes a customer object in the data access layer using the use force resource cleanup session to load the Customer object, and NHibernate immediately loads the customer-associated order object. Use NHibernate to provide a utility class (Nhibernateutil) to test whether the associated Customer object collection has been initialized (that is, loaded).

[test]public void Eagerloadusinglazyfalsetest () {    Customer customer = _relation. Lazyloadusingsession (1);    Assert.istrue (nhibernateutil.isinitialized (customer. Orders));}

The test was successful, proving that nhibernate immediately loaded the order object and found that two SQL statements were generated: the first queries the customer object, and the second statement queries its associated order object collection.

SELECT customer0_. CustomerId as customerid9_0_,       customer0_. Version as version9_0_,       customer0_. Firstname as firstname9_0_,       customer0_. Lastname as Lastname9_0_from Customer customer0_ WHERE [email protected]; @p0 = ' 1 ' SELECT orders0_. Customer as Customer1_,       orders0_. OrderId as Orderid1_,       orders0_. OrderId as orderid6_0_,       orders0_. Version as version6_0_,       orders0_. OrderDate as orderdate6_0_,       orders0_. Customer as Customer6_0_from [Order] orders0_ WHERE [email protected]; @p0 = ' 1 '

However, a careful friend will find that the type of the Orders object collection is Iesi.Collections.Generic.HashedSet ' 1[domainmodel.entities.order], In the previous section, the Orders object collection is this type only if you have not used the using force shutdown resource, and in the case of forcing resource shutdown, The Orders object collection is of type:nhibernate.collection.generic.persistentgenericset<domainmodel.entities.order>, Further reading of the order entry throws a Hibernateexception exception. I want to explain the immediate loading mechanism from this point of view.

Well, here it is, or change the mapping file to the original default (that is, remove lazy= "false") and see what other methods are available to load immediately.

2. Using the Nhibernateutil utility class

NHibernate provides a utility class (Nhibernateutil) not only is the light used to test whether the associated collection of objects has been initialized, but also a very important feature is the ability to force the initialization of an uninitialized associated object . With this feature, we can modify the methods in the data access layer, and add the Nhibernateutil class to provide the Initialize method to initialize the collection of order objects associated with the customer by using the use-forced cleanup method in the closed session.

Public Customer eagerloadusingsessionandnhibernateutil (int customerId) {    using (isession _session = new SessionManager (). GetSession ())    {        Customer customer= _session. Get<customer> (customerId);        Nhibernateutil.initialize (Customer. Orders);        return customer;    }}

Let's write a method to test:

[test]public void Eagerloadusingsessionandnhibernateutiltest () {    Customer customer = _relation. Eagerloadusingsessionandnhibernateutil (1);    Assert.istrue (nhibernateutil.isinitialized (customer. Orders));}

The test succeeds, and the result is the same as modifying the mapping file.

2. Many-to-many relationship instances 1. Use lazy= "false" property

Similarly, using the lazy= "false" property to set the immediate load behavior, you do not have to declare the virtual property for its public methods, properties, and events in a persisted class, because lazy loading is not used. But here I still recommend that you use nhibernate default lazy load behavior, the reason is very simple, nhibernate delay loading performance can be improved a lot, in special cases use the following method to load immediately.

This example is similar to the above, here is not to mention the example of repetition, we can test it by ourselves.

2. Using the Nhibernateutil utility class

If you need to get the associated object for the order entity, you can use the Nhibernateutil class to initialize the associated object (remove them from the database). Take a look at the methods in the data access layer below, using the Nhibernateutil class to provide the Initialize method to initialize the associated customer and product objects.

Public DomainModel.Entities.Order     eagerloadorderaggregatesessionandnhibernateutil (int orderId) {    using ( ISession _session = new SessionManager (). GetSession ())    {        DomainModel.Entities.Order Order =            _session. Get<domainmodel.entities.order> (orderId);        Nhibernateutil.initialize (order. Customer);        Nhibernateutil.initialize (order. Products);        return order;    }}

Test the method above:

[test]public void Eagerloadorderaggregatesessionandnhibernateutiltest () {    Order order =         _relation. Eagerloadorderaggregatesessionandnhibernateutil (2);    Assert.istrue (nhibernateutil.isinitialized (order. Customer));    Assert.istrue (nhibernateutil.isinitialized (order. Products));    Assert.AreEqual (order. Products.count, 2);}

Look at the SQL statements generated by NHibernate, that's a lot, a one-to-many relationship, an immediate load of many-to-many relationships generates four SQL statements, each querying the order table, the Customer table, and the product associated with the Orderproduct table. (The customer and order one-to-many relationship is also immediately loaded here), when the contents of the memory are the values of these associated objects, you are not each object to use, why should all load it.

SELECT order0_. OrderId as orderid6_0_, order0_. Version as version6_0_, order0_. OrderDate as orderdate6_0_, order0_. Customer as Customer6_0_from [Order] order0_ WHERE [email protected]; @p0 = ' 2 ' SELECT customer0_. CustomerId as customerid9_0_, customer0_. Version as version9_0_, customer0_. Firstname as firstname9_0_, customer0_. Lastname as Lastname9_0_from Customer customer0_ WHERE [email protected]; @p0 = ' 1 ' SELECT orders0_. Customer as Customer1_, orders0_. OrderId as Orderid1_, orders0_. OrderId as orderid6_0_, orders0_. Version as version6_0_, orders0_. OrderDate as orderdate6_0_, orders0_. Customer as Customer6_0_from [Order] orders0_ WHERE [email protected]; @p0 = ' 1 ' SELECT products0_. [Order] as order1_1_, products0_. Product as Product1_, product1_. ProductId as productid8_0_, product1_. Version as version8_0_, product1_. Name as name8_0_, product1_. Cost as Cost8_0_from orderproduct Products0_ left OUTER join Product product1_ on products0_. Product=product1_. Productidwhere products0_. [Order] [email protected]; @p0 = ' 2 '
3. Using the HQL crawl strategy

Using the HQL Query method can also be loaded immediately. The HQL statement supports the following types of connections: INNER JOIN (inner join), left OUTER join (off outer join), right outer join (off-side connection), full join (fully connected, not common).

The fetch fetch connection allows an associated object to be initialized with the initialization of their parent object using only a single selection statement, which effectively replaces the outer join and deferred attribute declarations in the mapping file.

Some notes:

    • Fetch is not shared with setmaxresults () or Setfirstresult () because these operations are based on the result set, and may contain duplicate data when the collection is pre-fetched, meaning that the exact number of rows cannot be known beforehand.
    • Fetch cannot be used with a standalone with condition. By fetch multiple sets in a single query, you can create a Cartesian product, so please pay more attention. For many-to-many mappings, also be careful that join fetch multiple collection roles may give unexpected results in some cases.
    • There is no point in using full join fetch with RIGHT join FETCH. If you use attribute-level deferred fetching, you can use the fetch all property in the first query to force NHibernate to immediately get those properties that would otherwise require lazy loading.

Here is a simple example:

Public DomainModel.Entities.Order eagerloadorderaggregatewithhql (int orderId) {    using (isession _session = new SessionManager (). GetSession ())    {        return _session. CreateQuery ("from Order o" +            "left OUTER join fetch o.products" +            "INNER join fetch O.customer where o.orderid=:o Rderid ")            . SetInt32 ("OrderId", OrderId)            . Uniqueresult<domainmodel.entities.order> ();    }}

Write a test case test the method above: Verify that building a HQL query loads not only the order, but also the associated customer and product objects.

[test]public void Eagerloadorderaggregatewithhqltest () {    Order order = _relation. EAGERLOADORDERAGGREGATEWITHHQL (2);    Assert.istrue (nhibernateutil.isinitialized (order. Customer));    Assert.istrue (nhibernateutil.isinitialized (order. Products));    Assert.AreEqual (order. Products.count, 2);}

Generating SQL statements through NHibernate can indicate that NHibernate can immediately load order and all order-related customer and product objects in a breath. The SQL statements are generated as follows:

Select Order0_. OrderId as orderid6_0_, product2_. ProductId as Productid8_1_, customer3_. CustomerId as Customerid9_2_, order0_. Version as version6_0_, order0_. OrderDate as orderdate6_0_, order0_. Customer as customer6_0_, product2_. Version as Version8_1_, product2_. Name as Name8_1_, product2_. Cost as cost8_1_, customer3_. Version as Version9_2_, customer3_. Firstname as Firstname9_2_, customer3_. Lastname as Lastname9_2_, products1_. [Order] as order1_0__, products1_. Product as Product0__from [Order] order0_left outer join orderproduct products1_ on order0_. Orderid=products1_. [Order]left outer join Product product2_ on products1_. Product=product2_. Productidinner join Customer customer3_ on order0_. Customer=customer3_. Customeridwhere ([email protected]); @p0 = ' 2 ' SELECT orders0_. Customer as Customer1_, orders0_. OrderId as Orderid1_, orders0_. OrderId as orderid6_0_, orders0_. Version as version6_0_, orders0_. OrderDate as orderdate6_0_, orders0_. Customer as Customer6_0_from [Order] orders0_ WHERE [email protected]; @p0 = ' 1 '

By using the HQL crawl strategy, you can write your desired results well in your program.

Go NHibernate Tour (13): A preliminary study on the immediate loading mechanism

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.