Add, delete, modify, and query hibernate associated objects ------ query, hibernate ------
This blog post is the addition, deletion, modification, and query of hibernate-related objects in the previous blog. the settings of this Code have been written in the previous article. Therefore, before reading this article, please move to the previous blog
// Code piece 5
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); Session session = sessionFactory.getCurrentSession(); session.beginTransaction(); Dream d=new Dream(); d.setDescription("marry glt"); Person p=new Person(); p.setName("dlf"); d.setPerson(p); session.save(d); session.save(p); session.getTransaction().commit(); session = sessionFactory.getCurrentSession(); session.beginTransaction(); Dream dream=(Dream) session.get(Dream.class, 1); System.out.println(dream.getPerson().getName()+" ddddd"); session.getTransaction().commit();
For Code 5, the SQL statement sent when get dream is
select dream0_.id as id0_1_, dream0_.description as descript2_0_1_, dream0_.personId as personId0_1_, person1_.id as id1_0_, person1_.myname as myname1_0_ from Dream dream0_ left outer join Person person1_ on dream0_.personId=person1_.id where dream0_.id=?
In other words, when we get dream, we also get the corresponding person.
Three Problems
1. When Code 5 is executed, the cascade of manytoone of dream has been removed.
2. If you put Dream dream = (Dream) session. get (Dream. class, 1); in the same session as the statement of the previously saved object, the SQL statement sent is update. However, System. out. println (dream. getPerson (). getName () + "ddddd"); can still enter the name of person.
We can draw a rule
In the case of multiple-to-one and one-to-multiple operations, when we read multiple parties, one party will also be read by default. (This rule is irrelevant to cascade)
In turn, if I read one, will I automatically read more?
Let's look at the code
// Code 6 public void testGetPerson () {Session s = sessionFactory. getCurrentSession (); s. beginTransaction (); Person p = (Person) s. get (Person. class, 2); s. getTransaction (). commit ();}
At this time, the SQL statement it sends is:
select person0_.id as id1_0_, person0_.myname as myname1_0_ from Person person0_ where person0_.id=?
Did not take the initiative to get the dream corresponding to the person.
What if I want to get dream?
Another parameter in the hibernate management relationship is fetch. It determines whether to read another related object when reading an object.
By reading the api documentation, we know that the fetch value is of the fetchtype type. Fetchtype is an Enum type.
Available values: LAZY and EAGER.
What do these two values mean?
In a guess, we all know that eager actively acquires the data of the associated object, and lazy does not obtain the data.
I can only say that it is probably correct.
Let's look at the code
Modify the onetoworkflow attribute in Person.
@OneToMany(mappedBy="person",fetch=FetchType.EAGER) public Set<Dream> getDreams() { return dreams; }
Run Code 6 again. The SQL statement is:
select person0_.id as id1_1_, person0_.myname as myname1_1_, dreams1_.personId as personId3_, dreams1_.id as id3_, dreams1_.id as id0_0_, dreams1_.description as descript2_0_0_, dreams1_.personId as personId0_0_ from Person person0_ left outer join Dream dreams1_ on person0_.id=dreams1_.personId where person0_.id=?
We can know that if we want to obtain more than one party at the same time, we will add fetch = feachType. eager to one party.
Then we can guess from the previous Code
By default
The fetch of the first party is lazy.
The fetch of the other party is eager.
Modify the association relationship with eager: hibernate sends the associated SQL
Use lazy to modify the link: hibernate does not
ActiveAssociation SQL
Note: what I mentioned above is to use lazy to modify associations: hibernate will not send associated SQL statements.
Why is it proactive? Take a look at the following code
Let's change Code 6.
// Code 7 public void testGetPerson () {Session s = sessionFactory. getCurrentSession (); s. beginTransaction (); Person p = (Person) s. get (Person. class, 2); System. out. println (p. getDreams (). size (); s. getTransaction (). commit ();}
In this case, the fetch value of person is not set. (Keep the default lazy)
The SQL statement is:
Hibernate: select person0_.id as id1_0_, person0_.myname as myname1_0_ from Person person0_ where person0_.id=?Hibernate: select dreams0_.personId as personId1_, dreams0_.id as id1_, dreams0_.id as id0_0_, dreams0_.description as descript2_0_0_, dreams0_.personId as personId0_0_ from Dream dreams0_ where dreams0_.personId=?
At this point, we can draw a conclusion that, if we only obtain the "one" side in the session, hibernate will not retrieve the other side by default; but if it is in the session, access the data of the "many" side in "1" (that is, access the dream in person) obtained ). The associated SQL statement is sent.
As a result, there is an embarrassing thing.
No matter whether I set fetch = FetchType. eager on the one side, it is okay for me to obtain more than one side in the session.
At this time, it is better not to set fetch = FetchType. what about the eager? Sometimes, I do not need to obtain more than one party. If one party is set to eager, it is not necessary to query a lot of useless data.
Let's look at another example:
// Code 8 public void testGetPerson () {testSavePerson (); Session s = sessionFactory. getCurrentSession (); s. beginTransaction (); Person p = (Person) s. get (Person. class, 2); s. getTransaction (). commit (); System. out. println (p. getDreams (). size ());}
It is to put the code that gets more data from that party out of the session.
If there is fetch = FetchType. eager on the person side, everything is OK.
On-screen output:
Hibernate: select person0 _. id as id1_1 _, person0 _. myname as myname1_1 _, dreams1 _. personId as personId3 _, dreams1 _. id as id3 _, dreams1 _. id as id0_0 _, dreams1 _. description as descript2_0_0 _, dreams1 _. personId as personId0_0 _ from Person person0 _ left outer join Dream dreams1 _ on person0 _. id = dreams1 _. personId where person0 _. id =? 2 // the size of dream is 2
If I remove fetch = FetchType. eager and run code 8, an error is returned:
<span style="color:#FF0000;">failed to lazily initialize a collection of role: com.bjsxt.hibernate.Person.dreams, no session or session was closed</span>
It is clear that the session has been closed.
Why?
We know that from person to dream is one-to-many, and by default, one-to-many fetch is lazy.
That is to say, normally, pseron won't be used again.
Note that the SQL statement sent by code 7 is two.
Now I want to get more commands and run them out of the sesssion. That is to say, if I run the SQL statement in the database after the session is closed, I will definitely report an error.
Let's try again:
// Code 9 public void testGetPerson () {testSavePerson (); Session s = sessionFactory. getCurrentSession (); s. beginTransaction (); Person p = (Person) s. get (Person. class, 2); s. getTransaction (). commit (); System. out. println (p. getDreams (). size (); s. getTransaction (). commit ();}
At this time, the fetch of person is still the default lazy.
Will an error be reported? Try it by yourself.
Hibernate is still troublesome for getting objects. I think the best way is to keep the default value. If there is a problem, check the api documentation or other materials.
Now, why should I write this blog? The best way is to keep the default value.
Because:
Qi Wei of the world, strange and extraordinary view, often lies in the danger of far, and the people of the unknown, so do not have to do.
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.