<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Teacher" table="teacher" >
<id name="id" type="int">
<column name="id" />
<generator class="identity"/>
</id>
<property name="teacherName" type="string"/>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Student" table="student" lazy="false">
<id name="id" type="integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="studentName" type="string" />
<many-to-one name="teacher" column="techer_id" class="Teacher" lazy="true" unique="true"/>
</class>
</hibernate-mapping>
在上述的xml中<many-to-one>标签说明存在一个多对一的映射关系,多对一的属性为Student类中的teacher属性(name的值),对应表中的列名为"teach_id"(column的值),映射关系另一方的类为Teacher类,这里需要写类全名,包括包名(class的值),lazy为延迟加载,俗称懒的初始化,为true时,在select 学生对象时,不会加载Teacher类对象,当需要一对一的关联关系时,红字部分为必须的,保证关系方的唯一性。在多对一的时候unique则为false
实际上,这里隐藏的告诉了Hibernate,teacher_id是外键,要引用Teacher类对应表的主键。
说这些是为了下面我们会使用Hibernate的一个类来为我们生成表。而不需要手动建表了:
public class CreateTable {
public static void main(String[] args) {
Configuration config = new Configuration().configure();
System.out.println("通过映射文件生成数据库的表");
SchemaExport se = new SchemaExport(config);
se.create(true, true);
System.out.println("完成生成数据库表");
}
}
在让Hibernate为我们建表之前,需要把Teacher.hbm.xml和Student.hbm.xml写好,并且添加进Hibernate.cfg.xml中的Mapping标签中。
反过来关联,一个老师对应多个学生的单向关联,一对多的关联关系如下:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Student" table="student" lazy="false">
<id name="id" type="integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="studentName" type="string" />
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Teacher" table="teacher">
<id name="id" type="int">
<column name="id" />
<generator class="identity" />
</id>
<property name="teacherName" type="string" />
<set name="students" inverse="false" fetch="select" cascade="save-update"
lazy="false">
<key column="teacher_id" />
<one-to-many class="Student" />
</set>
</class>
</hibernate-mapping>
关于<set>标签中的各个元素:
name:需要描述映射关系的类属性名
inverse:反转,默认为false,当为false的时候每次更新一次被关联方,就会再次更新一次关联方数据
fetch:指定了关联对象抓取的方式是select查询还是join查询,select方式时先查询返回要查询的主体对象(列表),再根据关联外键id,每一个对象发一个select查询,获取关联的对象,形成n+1次查询;而join方式,主体对象和关联对象用一句外键关联的sql同时查询出来,不会形成多次查询。如果关联的对象lazy=true,它不会去查询关联对象。
(通常情况下,我们并不使用映射文档进行抓取策略的定制。更多的是,保持其默认值,然后在特定的事务中,使用HQL的左连接抓取(left join fetch) 对其进行重载。这将通知 Hibernate在第一次查询中使用外部关联(outer join),直接得到其关联数据。 在条件查询 API中,应该调用 setFetchMode(FetchMode.JOIN)语句。 )
<key column="teacher_id" />:Student类对应表的关联外键为teacher_id
<one-to-many>:关联对方的class类型为:这里要类全名,包括包名。
一对多(多对一)的双向关联:
就是把上述两种关联方式结合起来。
老师的POJO类:
学生的POJO类:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Teacher" table="teacher">
<id name="id" type="int">
<column name="id" />
<generator class="identity" />
</id>
<property name="teacherName" type="string" />
<set name="students" inverse="true" fetch="select" cascade="delete"
lazy="false">
<key column="teacher_id" />
<one-to-many class="Student" />
</set>
</class>
</hibernate-mapping>
学生类的映射文件Student.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Student" table="student" lazy="false">
<id name="id" type="integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="studentName" type="string" />
<many-to-one name="teacher" column="techer_id" class="Teacher" lazy="true"/>
</class>
</hibernate-mapping>
注意的是,不能在双方同时指定级联操作cascade="save-update",这样会产生一个org.hibernate.ObjectDeletedException。
因为删除操作也是属于update操作,在删除时,会激发关联的save方法,这是不允许的。