我有两个基本的域类:
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...
}
这是类的hibernate映射文件:
<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>
如果我执行以下操作:
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();
执行以下SQL语句:
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 (?, ?)
最后,问题是:
为什么session.load(Event.class, 4L);
使用如上所示的内连接?而不只是在事件表上选择ID = 4的简单选择?
答案 0 :(得分:0)
内部联接是由人和事件的多对多映射造成的。在添加事件之前,Person.getEvents()
加载了一个人的所有事件。
<强>更新强>
session.load()
不需要数据库查询,因为session.load()
Hibernate假定存在具有给定id的实体(否则为Exception),并且只为给定的id生成代理。使用session.get()
Hibernate将转到数据库(如果具有此id的实体尚未在会话缓存或二级缓存中)并返回持久性实例。
我认为在调试代码时,不会在调用person.getEvents()
之前查看加载此人的查询。
希望有所帮助。
答案 1 :(得分:0)
我不确定,但是你想知道为什么没有SQL加载你的事件:
Event event = (Event) session.load(Event.class, 4L);
实际上,hibernate返回的事件bean不是一个简单的pojo,但通常是由一些魔术行为增强的类,允许执行延迟加载等等...(检查动态代理,CGLib / Javassist ......)< / p>
所以我不确定,但我猜你打电话的时候:
Event event = (Event) session.load(Event.class, 4L);
仅创建增强型事件bean,但不会触发SQL查询。如果你在非瞬态getter上调用,可能会触发sql,因为它还没有为getter返回的值。
最后我猜即使你把事件添加到人的事件集合中,也不需要触发sql,因为要创建该链接,你只需要事件id。 你猜怎么着?自从你在使用session.load时提供它后,它肯定已经知道了增强的事件bean - &gt;增强的类初始化为id = 4
这些只是假设,但尝试调用event.getSomething()以查看我是否正确;)