I have two basic domain classes:
public class Event {
private Long id;
private String title;
private Date date;
// getters/setters...
}
public class Person {
private Long id;
private int age;
private String firstname;
private String lastname;
private Set<Event> events = new HashSet();
// getters/setters...
}
This is the hibernate mapping file for the classes:
<class name="Event" table="EVENTS">
<id name="id" column="EVENT_ID">
<generator class="native"/>
</id>
<property name="date" type="timestamp" column="EVENT_DATE"/>
<property name="title"/>
</class>
<class name="Person" table="PERSON">
<id name="id" column="PERSON_ID">
<generator class="native"/>
</id>
<property name="age"/>
<property name="firstname"/>
<property name="lastname"/>
<set name="events" table="PERSON_EVENT">
<key column="PERSON_ID"/>
<many-to-many column="EVENT_ID" class="Event"/>
</set>
</class>
If I execute the following:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Person person = (Person) session.load(Person.class, 8L);
Event event = (Event) session.load(Event.class, 4L);
person.getEvents().add(event);
session.getTransaction().commit();
The following SQL statements are executed:
select
person0_.PERSON_ID as PERSON1_1_0_,
person0_.age as age1_0_,
person0_.firstname as firstname1_0_,
person0_.lastname as lastname1_0_
from PERSON person0_
where person0_.PERSON_ID=?
-- Why does this do an inner join?
select
events0_.PERSON_ID as PERSON1_1_1_,
events0_.EVENT_ID as EVENT2_1_,
event1_.EVENT_ID as EVENT1_0_0_,
event1_.EVENT_DATE as EVENT2_0_0_,
event1_.title as title0_0_
from PERSON_EVENT events0_
inner join EVENTS event1_ on events0_.EVENT_ID=event1_.EVENT_ID
where events0_.PERSON_ID=?
insert into PERSON_EVENT (PERSON_ID, EVENT_ID) values (?, ?)
So finally, the question:
Why does the session.load(Event.class, 4L); use an inner join as shown above? And not just a simple select on the Event table where the ID = 4?
The inner join is due to the many-to-many mapping of person and events. All the events of a person are loaded by
Person.getEvents()before the event can be added.UPDATE
There is no database query needed for
session.load()because withsession.load()Hibernate assumes the entity with the given id exists (Exception otherwise) and just generates a proxy for the given id. Withsession.get()Hibernate will go to the database (if the entity with this id is not already in the session cache or 2nd level cache) and return a persistent instance.I think when you debug your code you will also not see a query for loading the person until
person.getEvents()is called.Hope that helps.