The previous article introduced the cascade operation of Hibernate persistence object, this article introduces the cascade operation when reading.
Or use the previous example, a questionnaire has a number of questions, but each problem can only belong to a questionnaire. Let's look at the test case first:
@Test public void Testreadfromquestionnaire () {Session session = Sessionfactory. Getcurrentsession();Session. BeginTransaction();Questionnaire QN = (Questionnaire) session. Load(Questionnaire. Class,1);System. out. println*q,. GetName());Session. Gettransaction(). Commit();for (Question q:qn. Getquestions()) {System. out. println(q. GetName());} }
read out the ID 1 of the questionnaire, with QN, printed out the name of the questionnaire QN, finally I hope to print out the QN contains what problems, want to print out the problem dry content. But run:
org.hibernate.LazyInitializationException:com.ht.entity.one2manymany2one.bi.fetchcascade.Questionnaire.questionsor session was closed
Error, lazy loading exception, loading the required entities, questionnaire.question This association is not related.
Then the reason for this error is: Hibernate in the processing of a one-to-many relationship, the default is lazy loading, that is, I from a side (questionnaire) side, to read more than the party (Question) side, is not read, this can reduce the database burden, But in case I have this demand, I want to load out a lot of this side how to do it? The code is as follows:
@OneToMany(mappedBy="questionnaire",cascade={CascadeType.ALL},fetch=FetchType.EAGER) publicgetQuestions() { return questions; }
Here, configure the previous property fetch, the type is also enumerated, value eager, here is another value lazy
Erger: Hungry, that is, it will be loaded immediately.
Lazy: The associated object is not loaded
So the one-to-many default is lazy loading, where fetch is configured as eager, we look at the test results:
Hibernate:select questionna0_.ID asId6_1_, questionna0_.name asName6_1_, Questionna0_.answers asAnswers6_1_, Questions1_.questionnaireid asQuestion3_3_, questions1_.ID asId3_, questions1_.ID asId7_0_, questions1_.name asname7_0_, Questions1_.questionnaireid asquestion3_7_0_ fromT_questionnaire questionna0_ left outer join T_question questions1_ onquestionna0_.ID=questions1_.questionnaireidwherequestionna0_.ID=? XXX Company3Monthly Exam1, is Java an OOP language? A, is B, not2, which company's work is Java? A, SUN B, MicroSoft
Looking at the SQL statement, a LEFT outer join is used to query the associated object. No problem
There is also an interesting detail, the code is as follows:
@OneToMany(mappedBy="questionnaire",cascade={CascadeType.ALL}) publicgetQuestions() { return questions; }
Here I remove the hunger load and let him revert to the default lazy load, the test case is as follows:
@Test public void Testreadfromquestionnaire () {Session session = Sessionfactory. Getcurrentsession();Session. BeginTransaction();Questionnaire QN = (Questionnaire) session. Load(Questionnaire. Class,1);System. out. println*q,. GetName());for (Question q:qn. Getquestions()) {System. out. println(q. GetName());} session. Gettransaction(). Commit();}
The For loop is a problem in the Loop output questionnaire, and I put the For loop before the transaction commits, and then executes:
Hibernate:select questionna0_.ID asId6_0_, questionna0_.name asname6_0_, Questionna0_.answers asanswers6_0_ fromT_questionnaire questionna0_wherequestionna0_.ID=? XXX Company3Monthly Exam Hibernate:select Questions0_.questionnaireid asQuestion3_1_, questions0_.ID asId1_, questions0_.ID asId7_0_, questions0_.name asname7_0_, Questions0_.questionnaireid asquestion3_7_0_ fromT_question questions0_whereQuestions0_.questionnaireid=?1, is Java an OOP language? A, is B, not2, which company's work is Java? A, SUN B, MicroSoft
See, also loaded out, but do not take the associated object, look carefully at the SQL statement found that the first SQL statements executed separately, that is, from the questionnaire query once, and then go to the questionnaire ID to the problem table checked once, so do not cascade.
Then why did the for loop outside can also be found out, the reason is that after the hunger load, the questionnaire object, together with the problem of the subordinate object load to the memory, so the session closed can also read, so the loading mechanism and the difference is here.
Let's read the questionnaire from the question
@ManyToOne(cascade={CascadeType.ALL}) @JoinColumn(name="questionnaireId") publicgetQuestionnaire() { return questionnaire; }
The fetch attribute is not set here, we look at the test case:
@Test public void Testreadfromquestion () {Session session = Sessionfactory. Getcurrentsession();Session. BeginTransaction();Question q = (Question) session. Load(Question. Class,1);System. out. println(q. GetName());Session. Gettransaction(). Commit();System. out. println(q. GetName());}
To read the question ID 1, print the title and the name of the questionnaire:
Hibernate:select question0_.ID asId7_0_, question0_.name asname7_0_, Question0_.questionnaireid asquestion3_7_0_ fromT_question question0_wherequestion0_.ID=? Hibernate:select questionna0_.ID asId6_1_, questionna0_.name asName6_1_, Questionna0_.answers asAnswers6_1_, Questions1_.questionnaireid asQuestion3_3_, questions1_.ID asId3_, questions1_.ID asId7_0_, questions1_.name asname7_0_, Questions1_.questionnaireid asquestion3_7_0_ fromT_questionnaire questionna0_ left outer join T_question questions1_ onquestionna0_.ID=questions1_.questionnaireidwherequestionna0_.ID=?1, is Java an OOP language? A, is B, not xxx company3Monthly Exam
No problem, description, many to one of the default load one side is eager, so do not have to do more setup, if you do not want to load a side, then do the following settings:
@ManyToOne(cascade={CascadeType.ALL},fetch=FetchType.LAZY) @JoinColumn(name="questionnaireId") publicgetQuestionnaire() { return questionnaire; }
Setting the load mechanism to lazy is OK.
To summarize:
In the relationship of Onetomany (bidirectional):
From 1 to load N on this side, the default is lazy
from N to load 1 on this side, the default is eager
In the cascading and loading mechanism:
Cascade is only responsible for increasing, deleting, and changing the Cascade
If the read requires a cascade load, the Fetch attribute is used.
Hibernate cascade operation and loading mechanism (II) CASCADE and Fetch