Hibernate: 3. hibernate: 3.
Hibernate retrieval Policy
Reprinted Please note: TheViper http://www.cnblogs.com/TheViper
First look at a rough
1. Class Level
Instant retrieval <class lazy = 'false'>; delayed retrieval <class lazy = 'true'>. The default value is delayed retrieval.
If a persistent object is loaded to obtain its attributes, It is retrieved immediately. If it is only used to obtain its reference, it is loaded with delay. For example,
Friend_Category fc = new Friend_Category (); fc. setCategory_name ("existing friend category"); User_Friend_pk = new User_Friend_pk (); pk. setFriend_name ("New Friend"); pk. setName ("TheViper"); User_Friend uf = new User_Friend (); uf. setUser_friend_pk (pk); Friend_Category fc1 = (Friend_Category) session. load (Friend_Category.class, 1); uf. setFriend_categorys (fc1); // uf. setSort (""); session. saveOrUpdate (fc1); session. save (uf );
We can see that the Friend_Catagory class is loaded only to add new friends to existing friend categories. Here, load () is used to return a proxy class with only the id attribute in it. All other attributes are null, and not all attributes are returned. Therefore, the memory usage is very small.
In addition, whether the lazy attribute of <class> is true or false, get () and list () are always loaded immediately, however, it does not load the associated classes (the associated-level retrieval sets the default delay loading ).
2. association level
- One-to-many and multiple-to-many associated retrieval policies
Determined by the lazy and fetch attributes of <set>.
Lazy: determines the time when the associated set is initialized. That is, it is initialized during loading or accessed.
Fetch: When the value is select or subselect, it determines the form of the query statement when the associated set is initialized. When the value is fetch, it determines the time when the associated set is initialized, it is meaningless to explicitly set the lazy attribute.
When lazy = true, the proxy associated with the collection class will be initialized in the following situations:
1. The application accesses it for the first time, such as calling its iterator (), size (), isEmpty () or contains ().
2. Perform initialization through the initialize () Static Method of the org. hibernate. Hibernate class.
For lazy = extra, hibernate will further delay the initialization time of the associated object. Specifically, it is loaded only when the application calls the associated object's iterator () for the first time. Only this method works.
For lazy = false,
Feeling f = (Feeling) session.get(Feeling.class, 1);
<set name="feelingComments" inverse="true" lazy="false"> <key column="feeling_id" /> <one-to-many class="model.FeelingComment" /> </set>
When the Feeling class is taken out, the FeelingComment class is also taken out.
Hibernate: select feeling0_.feeling_id as feeling1_1_0_, feeling0_.content as content1_0_, feeling0_.id as id1_0_ from feeling feeling0_ where feeling0_.feeling_id =?Hibernate: select feelingcom0_.feeling_id as feeling3_1_1_, feelingcom0_.feelingComment_id as feelingC1_1_, feelingcom0_.feelingComment_id as feelingC1_2_0_, feelingcom0_.content as content2_0_, feelingcom0_.feeling_id as feeling3_2_0_, feelingcom0_.id as id2_0_ from feeling_comment feelingcom0_ where feelingcom0_.feeling_id=?
Set fetch = subselect below,
Session session = sf.openSession(); Transaction transaction = session.beginTransaction(); Query q = session.createQuery("from Feeling feeling"); List<Feeling> feelings = (List<Feeling>) q.list(); for (Feeling feeling : feelings) { Set comments = feeling.getFeelingComments(); System.out.println(comments); } transaction.commit(); session.close();
Hibernate: select feeling0_.feeling_id as feeling1_1_, feeling0_.content as content1_, feeling0_.id as id1_ from feeling feeling0_Hibernate: select feelingcom0_.feeling_id as feeling3_1_1_, feelingcom0_.feelingComment_id as feelingC1_1_, feelingcom0_.feelingComment_id as feelingC1_2_0_, feelingcom0_.content as content2_0_, feelingcom0_.feeling_id as feeling3_2_0_, feelingcom0_.id as id2_0_ from feeling_comment feelingcom0_ where feelingcom0_.feeling_id in ( select feeling0_.feeling_id from feeling feeling0_ )[model.FeelingComment@17f2fe3, model.FeelingComment@1211a4b, model.FeelingComment@533fc3][model.FeelingComment@a9a994, model.FeelingComment@455d96][model.FeelingComment@35c6f]
We can see that hibernate uses the in subquery method to capture associated objects, and the batch-size attribute is ignored.
Fetch = join indicates that the search policy of the left Outer join is used to capture associated objects. Note that list () automatically ignores this setting, which is very important.
Or the above Code, the result
Hibernate: select feeling0_.feeling_id as feeling1_1_, feeling0_.content as content1_, feeling0_.id as id1_ from feeling feeling0_Hibernate: select feelingcom0_.feeling_id as feeling3_1_1_, feelingcom0_.feelingComment_id as feelingC1_1_, feelingcom0_.feelingComment_id as feelingC1_2_0_, feelingcom0_.content as content2_0_, feelingcom0_.feeling_id as feeling3_2_0_, feelingcom0_.id as id2_0_ from feeling_comment feelingcom0_ where feelingcom0_.feeling_id=?[model.FeelingComment@1fbf047, model.FeelingComment@82a092, model.FeelingComment@15bd7c5]Hibernate: select feelingcom0_.feeling_id as feeling3_1_1_, feelingcom0_.feelingComment_id as feelingC1_1_, feelingcom0_.feelingComment_id as feelingC1_2_0_, feelingcom0_.content as content2_0_, feelingcom0_.feeling_id as feeling3_2_0_, feelingcom0_.id as id2_0_ from feeling_comment feelingcom0_ where feelingcom0_.feeling_id=?[model.FeelingComment@c407e, model.FeelingComment@5e3212]Hibernate: select feelingcom0_.feeling_id as feeling3_1_1_, feelingcom0_.feelingComment_id as feelingC1_1_, feelingcom0_.feelingComment_id as feelingC1_2_0_, feelingcom0_.content as content2_0_, feelingcom0_.feeling_id as feeling3_2_0_, feelingcom0_.id as id2_0_ from feeling_comment feelingcom0_ where feelingcom0_.feeling_id=?[model.FeelingComment@69757f]
In this case, setting the lazy and batch-size attributes is meaningless.
The batch-size attribute is used to set the number of batch queries for the search policy, which can reduce the number of select statements and provide the search running performance.
For example, if the batch-size is set to 2, the associated set contains three objects.
Session session = sf.openSession(); Transaction transaction = session.beginTransaction(); Query q = session.createQuery("from Feeling feeling"); List<Feeling> feelings = (List<Feeling>) q.list(); for (Feeling feeling : feelings) { Set comments = feeling.getFeelingComments(); System.out.println(comments); } transaction.commit(); session.close();
Hibernate: select feeling0_.feeling_id as feeling1_1_, feeling0_.content as content1_, feeling0_.id as id1_ from feeling feeling0_Hibernate: select feelingcom0_.feeling_id as feeling3_1_1_, feelingcom0_.feelingComment_id as feelingC1_1_, feelingcom0_.feelingComment_id as feelingC1_2_0_, feelingcom0_.content as content2_0_, feelingcom0_.feeling_id as feeling3_2_0_, feelingcom0_.id as id2_0_ from feeling_comment feelingcom0_ where feelingcom0_.feeling_id in ( ?, ? )[model.FeelingComment@177151, model.FeelingComment@16e125, model.FeelingComment@110a0ca]Hibernate: select feelingcom0_.feeling_id as feeling3_1_1_, feelingcom0_.feelingComment_id as feelingC1_1_, feelingcom0_.feelingComment_id as feelingC1_2_0_, feelingcom0_.content as content2_0_, feelingcom0_.feeling_id as feeling3_2_0_, feelingcom0_.id as id2_0_ from feeling_comment feelingcom0_ where feelingcom0_.feeling_id=?[model.FeelingComment@1c8f247, model.FeelingComment@1d67998][model.FeelingComment@ac44e3]
Note: If you use iterator () to return data for the Query interface, the batch-size will be ignored!
Hibernate: select feeling0_.feeling_id as col_0_0_ from feeling feeling0_Hibernate: select feeling0_.feeling_id as feeling1_1_0_, feeling0_.content as content1_0_, feeling0_.id as id1_0_ from feeling feeling0_ where feeling0_.feeling_id =?Hibernate: select feelingcom0_.feeling_id as feeling3_1_1_, feelingcom0_.feelingComment_id as feelingC1_1_, feelingcom0_.feelingComment_id as feelingC1_2_0_, feelingcom0_.content as content2_0_, feelingcom0_.feeling_id as feeling3_2_0_, feelingcom0_.id as id2_0_ from feeling_comment feelingcom0_ where feelingcom0_.feeling_id=?[model.FeelingComment@ee7d2a, model.FeelingComment@fb3758, model.FeelingComment@17596bc]Hibernate: select feeling0_.feeling_id as feeling1_1_0_, feeling0_.content as content1_0_, feeling0_.id as id1_0_ from feeling feeling0_ where feeling0_.feeling_id =?Hibernate: select feelingcom0_.feeling_id as feeling3_1_1_, feelingcom0_.feelingComment_id as feelingC1_1_, feelingcom0_.feelingComment_id as feelingC1_2_0_, feelingcom0_.content as content2_0_, feelingcom0_.feeling_id as feeling3_2_0_, feelingcom0_.id as id2_0_ from feeling_comment feelingcom0_ where feelingcom0_.feeling_id=?[model.FeelingComment@855e17]Hibernate: select feeling0_.feeling_id as feeling1_1_0_, feeling0_.content as content1_0_, feeling0_.id as id1_0_ from feeling feeling0_ where feeling0_.feeling_id =?Hibernate: select feelingcom0_.feeling_id as feeling3_1_1_, feelingcom0_.feelingComment_id as feelingC1_1_, feelingcom0_.feelingComment_id as feelingC1_2_0_, feelingcom0_.content as content2_0_, feelingcom0_.feeling_id as feeling3_2_0_, feelingcom0_.id as id2_0_ from feeling_comment feelingcom0_ where feelingcom0_.feeling_id=?[model.FeelingComment@85ba73, model.FeelingComment@191bae7]
Iterator () See the previous description.
- Multiple-to-one and one-to-one Retrieval Strategies
Fetch = join
<set name="feelingComments" inverse="true"> <key column="feeling_id" /> <one-to-many class="model.FeelingComment" /> </set>
<many-to-one name="feelings" column="feeling_id" class="model.Feeling" not-null="false" fetch="join"> </many-to-one>
FeelingComment f = (FeelingComment) session .get(FeelingComment.class, 1);
Hibernate: select feelingcom0_.feelingComment_id as feelingC1_2_1_, feelingcom0_.content as content2_1_, feelingcom0_.feeling_id as feeling3_2_1_, feelingcom0_.id as id2_1_, feeling1_.feeling_id as feeling1_1_0_, feeling1_.content as content1_0_, feeling1_.id as id1_0_ from feeling_comment feelingcom0_ left outer join feeling feeling1_ on feelingcom0_.feeling_id=feeling1_.feeling_id where feelingcom0_.feelingComment_id =?
The above is very simple. Change the value by adding lazy = false in <set>.
Hibernate: select feelingcom0_.feelingComment_id as feelingC1_2_1_, feelingcom0_.content as content2_1_, feelingcom0_.feeling_id as feeling3_2_1_, feelingcom0_.id as id2_1_, feeling1_.feeling_id as feeling1_1_0_, feeling1_.content as content1_0_, feeling1_.id as id1_0_ from feeling_comment feelingcom0_ left outer join feeling feeling1_ on feelingcom0_.feeling_id=feeling1_.feeling_id where feelingcom0_.feelingComment_id =?Hibernate: select feelingcom0_.feeling_id as feeling3_1_1_, feelingcom0_.feelingComment_id as feelingC1_1_, feelingcom0_.feelingComment_id as feelingC1_2_0_, feelingcom0_.content as content2_0_, feelingcom0_.feeling_id as feeling3_2_0_, feelingcom0_.id as id2_0_ from feeling_comment feelingcom0_ where feelingcom0_.feeling_id=?
As you can see, two SQL statements are sent this time, and the feeling_comment will be retrieved again based on feeling_id for the second time. I personally feel meaningless. This does not happen in one-to-many and many-to-many scenarios.
In addition, list () will be like one-to-many and many-to-many, ignoring fetch = join.
Lazy = proxy (default)
This is like lazy = true in one-to-many and many-to-many. That is, when querying the "multiple" side, the associated objects in the "one" side are not queried. It is initialized only when an associated object is used.
Note that for <one-to-one>, you must set constrained = true, indicating that the correlated object on the "1" side cannot be empty.
Lazy = no-proxy
This is very similar to lazy = proxy. However, the bytecode needs to be enhanced during compilation, otherwise it is no different from the proxy.
The effect after this is done.
FeelingComment f = (FeelingComment) session .get(FeelingComment.class, 1); Feeling f1 = f.getFeelings(); f1.getContent();
When getFeelings () is run, hibernate sends an SQL statement. When lazy = proxy is run, it is sent only when getContent () is run.
Lazy = false
When running to get (), two SQL statements are sent.
Hibernate: select feelingcom0_.feelingComment_id as feelingC1_2_0_, feelingcom0_.content as content2_0_, feelingcom0_.feeling_id as feeling3_2_0_, feelingcom0_.id as id2_0_ from feeling_comment feelingcom0_ where feelingcom0_.feelingComment_id =?Hibernate: select feeling0_.feeling_id as feeling1_1_0_, feeling0_.content as content1_0_, feeling0_.id as id1_0_ from feeling feeling0_ where feeling0_.feeling_id =?
If
<many-to-one name="feelings" column="feeling_id" class="model.Feeling" not-null="false" lazy="false">
At the same time
<class name="model.Feeling" table="feeling" lazy="false"> </class>
The SQL statement is the same as fetch = join.
FeelingComment f = (FeelingComment) session .get(FeelingComment.class, 1);
Hibernate: select feelingcom0_.feelingComment_id as feelingC1_2_1_, feelingcom0_.content as content2_1_, feelingcom0_.feeling_id as feeling3_2_1_, feelingcom0_.id as id2_1_, feeling1_.feeling_id as feeling1_1_0_, feeling1_.content as content1_0_, feeling1_.id as id1_0_ from feeling_comment feelingcom0_ left outer join feeling feeling1_ on feelingcom0_.feeling_id=feeling1_.feeling_id where feelingcom0_.feelingComment_id =?
Use batch search in many-to-one and one-to-one scenarios
In <batch-to-one>, <one-to-one>, there is no batch-size attribute. You need to set batch-size for "1. for example, you need to add three associated instances (1), batch-size = 2.
<class name="model.Feeling" table="feeling" batch-size="2"> </class>
Query q = session.createQuery("from FeelingComment"); List<FeelingComment> feelings = (List<FeelingComment>) q.list(); for (FeelingComment feelingComment : feelings) { Feeling feeling = feelingComment.getFeelings(); System.out.println(feeling); }
Hibernate: select feelingcom0_.feelingComment_id as feelingC1_2_, feelingcom0_.content as content2_, feelingcom0_.feeling_id as feeling3_2_, feelingcom0_.id as id2_ from feeling_comment feelingcom0_Hibernate: select feeling0_.feeling_id as feeling1_1_0_, feeling0_.content as content1_0_, feeling0_.id as id1_0_ from feeling feeling0_ where feeling0_.feeling_id in ( ?, ? )model.Feeling@1e684bdmodel.Feeling@1e684bdmodel.Feeling@1e684bdmodel.Feeling@1149b6cHibernate: select feeling0_.feeling_id as feeling1_1_0_, feeling0_.content as content1_0_, feeling0_.id as id1_0_ from feeling feeling0_ where feeling0_.feeling_id =?model.Feeling@fb8996model.Feeling@1149b6c
Note that the lazy in the above example is the default proxy. if lazy = false, run the command to feelingComment. getFeelings (); then the subsequent SQL statement is sent.
- Attribute-level retrieval Policy
You only need to set lazy = true on <property> and <component>. This policy applies to attributes of Binary large objects, string large objects, and large-capacity component types. For example, the image attribute of the User class stores the binary data of the image,
User user = (User) session. get (User. class, 1); user. getImage ();
When get () is run, hibernate does not load the image attribute. It is loaded only when it is run to getImage.
Note: When using this function, you must use multiple-to-one, one-to-one lazy = no-proxy, and the bytecode needs to be enhanced during compilation.