以主键关联
关联的两个实体共享一个主键。给一个表(Student)设定主键,另个一表(Certificate)使用的是学生表的主键,即主键的foreign生成机制。
Student.hbm.xml
<class name="model.Student" table="student" lazy="true"><!--把类和数表关联起来-->
<id name="id" unsaved-value="null"><!--id的产生方式是uuid.hex-->
<generator class="uuid.hex" />
</id>
<property name="cardId" type="string" /><!--映射号-->
<property name="name" type="string" /><!--映射学生名-->
<property name="age" type="int" /><!--映射学生岁数-->
<one-to-one name="cer"
class="model.Certificate"
fetch="join"
cascade="all"
/><!--映射对应的身分证对象-->
</class>
Certificate.hbm.xml
<class name="model.Certificate" table="certificate" lazy="true">
<id name="id">
<!-- 外键生成机制,引用stu对象的主键作为certificate数据表的外键和主键 -->
<generator class="foreign"><!-- 以主键关联 -->
<param name="property">stu</param>
</generator>
</id>
<!-- 下面的column属性加上了引号,是因为describe是mysql的关键字 -->
<property name="describe" column="`describe`" type="string" />
<one-to-one name="stu"
class="model.Student"
fetch="select"
constrained="true"
cascade="none"
/>
<!--constrained="true" 表示certificate应用了stu的主键作为外键 -->
</class>
一对一的关系是通过主键值得以关联的,而主键id在配置文件中已经设置过了,hibernate找到student,通过一对一关系找到certificate.hbm.xml,该配置文件中没有设置主键的列名,则默认列名为id,再去取得certificate的响应id的对象。
测试类:
Student stu = new Student();
stu.setName("spark");
stu.setCardId("200211332");
stu.setAge(33);
Certificate cer=new Certificate();
cer.setDescribe("spark");
stu.setCer(cer);
cer.setStu(stu);
StudentDAO.saveObj(stu);
控制台输出:
Hibernate: insert into student (cardId, name, age, id) values (?, ?, ?, ?)
Hibernate: insert into certificate (`describe`, id) values (?, ?)
以外键关联
重点是两个实体各有不相同的主键,其中一个实体有一个外键应用了另一个实体的主键。
Student.hbm.xml
<class name="model.Student" table="student" lazy="true"><!--把类和数表关联起来-->
<id name="id" unsaved-value="null"><!--id的产生方式是uuid.hex-->
<generator class="uuid.hex" />
</id>
<property name="cardId" type="string" /><!--映射号-->
<property name="name" type="string" /><!--映射学生名-->
<property name="age" type="int" /><!--映射学生岁数-->
<one-to-one name="cer" class="model.Certificate" fetch="join" cascade="all" /><!--映射对应的身分证对象-->
</class>
Certificate.hbm.xml
<class name="model.Certificate" table="certificate" lazy="true">
<id name="id">
<generator class="uuid.hex" />
</id>
<property name="describe" column="`describe`" type="string" />
<many-to-one name="stu"
class="model.Student"
unique="true" <!—唯一的多对一,也就成了一对一-->
column="stu_id"
/>
</class>
测试类:
Student stu = new Student();
stu.setName("spark");
stu.setCardId("200211332");
stu.setAge(33);
Certificate cer=new Certificate();
cer.setDescribe("spark");
stu.setCer(cer);
cer.setStu(stu);
StudentDAO.saveObj(stu);
控制台输出:
Hibernate: insert into student (cardId, name, age, id) values (?, ?, ?, ?)
Hibernate: insert into certificate (`describe`, id) values (?, ?)
默认的级联关系:
one-to-one关联默认的级联关系是预先抓取,而一对多,多对多的默认加载策略是立即记载。
延迟加载:
对one-to-one关系进行延迟加载和其他关系相比稍微不同。Many-to-one的延迟加载是在配置文件的class标签设置lazy=“true”,one-to-many和many-to-many的延迟加载是在set标签中设置lazy=“true”,而one-to-one不仅要在class标签设置lazy=“true”,而且要在one-to-one标签中设置constrained=“true”
Student.hbm.xml
<class name="model.Student" table="student" ><!--把类和数表关联起来-->
<id name="id" unsaved-value="null"><!--id的产生方式是uuid.hex-->
<generator class="uuid.hex" />
</id>
<property name="cardId" type="string" /><!--映射号-->
<property name="name" type="string" /><!--映射学生名-->
<property name="age" type="int" /><!--映射学生岁数-->
<one-to-one name="cer"
class="model.Certificate"
cascade="all"
/><!--映射对应的身分证对象-->
</class>
Certificate.hbm.xml
<class name="model.Certificate" table="certificate" lazy="true">
<id name="id">
<generator class="uuid.hex" />
</id>
<property name="describe" column="`describe`" type="string" />
<many-to-one name="stu"
class="model.Student"
unique="true"
column="stu_id"
/>
</class>
测试类:
StudentDAO.getById(Student.class,"5abfa70605c5356f0105c535730e0001");
控制台输出:
Hibernate: select student0_.id as id0_1_, student0_.cardId as cardId0_1_, student0_.name as name0_1_, student0_.age as age0_1_, certificat1_.id as id1_0_, certificat1_.`describe` as describe2_1_0_, certificat1_.stu_id as stu3_1_0_ from student student0_ left outer join certificate certificat1_ on student0_.id=certificat1_.id where student0_.id=?
此时在certificate的class标签中设置了lazy=“true”,但是没有在student的one-to-one标签中设置constrained=“true”,所以延迟加载不起作用,而是使用了默认的预先抓取策略。
在原来的student.hbm.xml文件做一点小改动,
<class name="model.Student" table="student" ><!--把类和数表关联起来-->
<id name="id" unsaved-value="null"><!--id的产生方式是uuid.hex-->
<generator class="uuid.hex" />
</id>
<property name="cardId" type="string" /><!--映射号-->
<property name="name" type="string" /><!--映射学生名-->
<property name="age" type="int" /><!--映射学生岁数-->
<one-to-one name="cer"
class="model.Certificate"
constrained="true"
cascade="all"
/><!--映射对应的身分证对象-->
</class>
控制台输出:
Hibernate: select student0_.id as id0_0_, student0_.cardId as cardId0_0_, student0_.name as name0_0_,
student0_.age as age0_0_
from student student0_ where student0_.id=?
对one-to-one关系,constrained=“true” 和附属类的lazy=“true“才能实现延迟加载,并且将忽略默认的预先抓取策略。