前言:在域模型中,类与类之间最普遍的关系就是关联关系,在UML语言中关联关系是有方向的。在数据库中表与表之间也会有关联关系,本节介绍通过Hibernate映射一对多的关联关系,这是一种最普遍的关联关系。
1.数据库表的一对多关联关系
(1)示例数据库表说明
本节使用两张表:tb_student(学生表)、tb_class(班级表),一个班级里有多个学生,而一个学生只能在一个班级里,这样构成了学生与班级的多对一关联关系。下图表述了Student与Class之间的关系:
(2)使用MySQL创建表
根据上面的关系图,在MySQL数据库中的建表语句如下:
CREATE TABLE tb_class
(
id bigint NOT NULL auto_increment COMMENT 'ID',
no varchar(10) NOT NULL COMMENT '班级编号',
name varchar(50) NOT NULL COMMENT '班级名称',
PRIMARY KEY (id)
) COMMENT '班级信息表';
CREATE TABLE tb_student
(
id bigint NOT NULL auto_increment COMMENT 'ID',
no varchar(10) NOT NULL COMMENT '学号',
name varchar(50) NOT NULL COMMENT '姓名',
sex char(1) NOT NULL COMMENT '性别',
birthday datetime COMMENT '出生日期',
class_id bigint NOT NULL COMMENT '班级ID',
PRIMARY KEY (id)
) COMMENT = '学生信息表';
以上的建表语句没有新建外键关联,班级信息表表与学生信息表表只是有逻辑上的关联关系,在数据库中并没有外键关联,这种情况下也可以正常使用Hibernate关联关系。本文提供的创建外键的DDL语句如下:
ALTER TABLE tb_student ADD CONSTRAINT fk_tb_student_tb_class_1 FOREIGN KEY (class_id) REFERENCES tb_class (id);
(3)编写对应的实体类
以下是根据tb_class表编写的实体类ClassInfo:
package model;
public class ClassInfo
{
private Long id;
private String no;
private String name;
private List<Student> students = new ArrayList<Student>();
//省略setter、getter、toString...
}
以下是根据tb_student表编写的实体类Student:
package model;
import java.sql.Date;
public class Student
{
private Long id;
private String no;
private String name;
private String sex;
private Date birthday;
private ClassInfo classInfo;
//省略setter、getter、toString...
}
注意:Hibernate要求在实体类中定义集合类属性时,必须把属性声明为接口类型,如:java.util.List、java.util.Set、java.util.Map。ClassInfo类的students属性就是用java.util.List接口。
2.建立多对一的单向关联关系
多对一的单向关联关系和关系数据库中的外键参照关系最匹配了,因此如果使用单向关联关系,通常选择从Studen到Class的多对一单向关联。使用多对一的单向关联映射使用many-to-one元素,配置如下:
- <hibernate-mapping package="model">
<class name="ClassInfo" table="tb_class">
<id name="id">
<generator class="native"></generator>
</id>
<property name="no" column="no"/>
<property name="name" column="name"/>
</class>
</hibernate-mapping>
<hibernate-mapping package="model">
<class name="Student" table="tb_student">
<id name="id">
<generator class="native"></generator>
</id>
<property name="no" column="no"/>
<property name="name" column="name"/>
<property name="sex" column="sex"/>
<property name="birthday" column="birthday"/>
<many-to-one name="classInfo" column="class_id" class="model.ClassInfo" lazy="false"/>
</class>
</hibernate-mapping>
关于以上many-to-one元素的配置说明如下:
- name:设置需要映射的实体类属性名。
- column:设置和实体类的属性对应的表的外键。注意:Hibernate默认此外键参照的是对应实体类的主键,在这里即是class_id参照classInfo实体类的id。
- class:设置需要映射的实体类属性的类型。
- lazy:是否使用懒加载,使用懒加载Hibernate会在你第一次访问关联的对象时才会去数据库取数据,不会立即去数据库检索与此对象关联的所有数据。
根据以上配置编写测试程序,测试程序的代码如下:
public static void main(String[] args)
{
Student student;
Configuration cfg = new Configuration();
cfg.configure();
ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
SessionFactory sf = cfg.buildSessionFactory(sr);
System.out.println("连接数据库");
Session session = sf.openSession();
student=(Student) session.get(Student.class, new Long(1));
System.out.println(student);
System.out.println(student.getClassInfo());
session.close();
System.out.println("关闭数据库");
System.exit(0);
}
现在还不能运行测试程序,在运行下、测试程序之前还要把新增的配置文件配置到hibernate.cfg.xml文件里,如下:
<hibernate-configuration>
<session-factory>
<!-- 省略其他...,设置实体类到数据库的映射文件 -->
<mapping resource="model/ClassInfo.hbm.xml"/>
<mapping resource="model/Student.hbm.xml"/>
</session-factory>
</hibernate-configuration>
运行程序,得到如下输出:
连接数据库
Hibernate:
select
student0_.id as id1_2_0_,
student0_.no as no2_2_0_,
student0_.name as name3_2_0_,
student0_.sex as sex4_2_0_,
student0_.birthday as birthday5_2_0_,
student0_.class_id as class_id6_2_0_
from
tb_student student0_
where
student0_.id=?
Hibernate:
select
classinfo0_.id as id1_1_0_,
classinfo0_.no as no2_1_0_,
classinfo0_.name as name3_1_0_
from
tb_class classinfo0_
where
classinfo0_.id=?
Student [id=1, no=000001, name=学生1, sex=男, birthday=2015-01-27]
ClassInfo [id=22, no=000022, name=班级22]
关闭数据库
从控制台输出中,我们可以看到在调用session.get方法得到Student对象时Hibernate生成了两条SQL语句查询出了Student对象和与这个Student关联的Class对象。
3.建立一对多的单向关联关系
我们也可以通过元素配置映射一对多的单向关联,但是一般情况下不推荐使用一对多的单向关联,更建议使用一对多的双向关联。使用一对多的单向关联需要使用one-to-many元素配置映射,具体配置如下:
<hibernate-mapping package="model">
<class name="Student" table="tb_student">
<id name="id">
<generator class="native"></generator>
</id>
<property name="no" column="no"/>
<property name="name" column="name"/>
<property name="sex" column="sex"/>
<property name="birthday" column="birthday"/>
</class>
</hibernate-mapping>
<hibernate-mapping package="model">
<class name="ClassInfo" table="tb_class">
<id name="id">
<generator class="native"></generator>
</id>
<property name="no" column="no"/>
<property name="name" column="name"/>
<bag name="students">
<key column="class_id"/>
<one-to-many class="model.Student"/>
</bag>
</class>
</hibernate-mapping>
由于ClassInfo类的students属性类型是List<Student>属于List集合,所以使用对应的bag元素配置,其配置说明如下:
- bag name:设置需要映射的实体类属性名。
- key column:设置和实体类的属性对应的表的外键。注意:Hibernate默认此外键参照的是对应实体类的主键,在这里即是class_id参照ClassInfo实体类的id。
- one-to-many class:设置需要映射的实体类属性的类型。
编写测试程序如下:
public static void main(String[] args)
{
ClassInfo classInfo;
Configuration cfg = new Configuration();
cfg.configure();
ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
SessionFactory sf = cfg.buildSessionFactory(sr);
System.out.println("连接数据库");
Session session = sf.openSession();
classInfo =(ClassInfo) session.get(ClassInfo.class, new Long(1));
System.out.println(classInfo);
System.out.println(classInfo.getStudents().size());
System.out.println(classInfo.getStudents().get(0));
session.close();
System.out.println("关闭数据库");
System.exit(0);
}
运行结果如下:
连接数据库
Hibernate:
select
classinfo0_.id as id1_1_0_,
classinfo0_.no as no2_1_0_,
classinfo0_.name as name3_1_0_
from
tb_class classinfo0_
where
classinfo0_.id=?
ClassInfo [id=1, no=000001, name=班级1]
Hibernate:
select
students0_.class_id as class_id6_1_0_,
students0_.id as id1_2_0_,
students0_.id as id1_2_1_,
students0_.no as no2_2_1_,
students0_.name as name3_2_1_,
students0_.sex as sex4_2_1_,
students0_.birthday as birthday5_2_1_,
students0_.class_id as class_id6_2_1_
from
tb_student students0_
where
students0_.class_id=?
35
Student [id=24, no=000024, name=学生24, sex=女, birthday=2015-01-27]
关闭数据库
根据输出结果可知当调用classInfo.getStudents().size()方法时,Hibernate会自动查询出ClassInfo对象关联的Student对象(第二个SQL)。从运行结果中看到Hibernate的两条SQL并不是连续执行的,这是由于Hibernate默认使用了懒加载,所以在程序访问ClassInfo类的students时Hibernate才会去数据库中取数据。
4.建立一对多的双向关联关系
(1)使用一对多双向关联
综合上面两个例子,同时使用元素和元素配置如下:
<hibernate-mapping package="model">
<class name="Student" table="tb_student">
<id name="id">
<generator class="native"></generator>
</id>
<property name="no" column="no"/>
<property name="name" column="name"/>
<property name="sex" column="sex"/>
<property name="birthday" column="birthday"/>
<many-to-one name="classInfo" column="class_id" class="model.ClassInfo" lazy="false"/>
</class>
</hibernate-mapping>
<hibernate-mapping package="model">
<class name="ClassInfo" table="tb_class">
<id name="id">
<generator class="native"></generator>
</id>
<property name="no" column="no"/>
<property name="name" column="name"/>
<bag name="students" inverse="false" cascade="none" lazy="false">
<key column="class_id"/>
<one-to-many class="model.Student"/>
</bag>
</class>
</hibernate-mapping>
测试程序如下:
public static void main(String[] args)
{
Student student;
Configuration cfg = new Configuration();
cfg.configure();
ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
SessionFactory sf = cfg.buildSessionFactory(sr);
System.out.println("连接数据库");
Session session = sf.openSession();
student=(Student) session.get(Student.class, new Long(1));
System.out.println(student);
System.out.println(student.getClassInfo());
System.out.println(student.getClassInfo().getStudents().size());
session.close();
System.out.println("关闭数据库");
System.exit(0);
}
控制台输出如下:
连接数据库
Hibernate:
select
student0_.id as id1_2_0_,
student0_.no as no2_2_0_,
student0_.name as name3_2_0_,
student0_.sex as sex4_2_0_,
student0_.birthday as birthday5_2_0_,
student0_.class_id as class_id6_2_0_
from
tb_student student0_
where
student0_.id=?
Hibernate:
select
classinfo0_.id as id1_1_0_,
classinfo0_.no as no2_1_0_,
classinfo0_.name as name3_1_0_
from
tb_class classinfo0_
where
classinfo0_.id=?
Hibernate:
select
students0_.class_id as class_id6_1_0_,
students0_.id as id1_2_0_,
students0_.id as id1_2_1_,
students0_.no as no2_2_1_,
students0_.name as name3_2_1_,
students0_.sex as sex4_2_1_,
students0_.birthday as birthday5_2_1_,
students0_.class_id as class_id6_2_1_
from
tb_student students0_
where
students0_.class_id=?
Student [id=1, no=000001, name=学生1, sex=男, birthday=2015-01-27]
ClassInfo [id=22, no=000022, name=班级22]
38
关闭数据库
由于我在配置文件中禁用了懒加载(lazy="false"),所以调用session.get(Student.class, new Long(1))时Hibernate连续执行了3条SQL语句从数据库中取出所有关联的数据!
(2)bag元素的inverse属性详解
由于ClassInfo类和Student类是双向关联,Hibernate默认会根据ClassInfo类或Student类维护其关联关系(即会执行相应的update语句),但是这会造成Hibernate执行不必要的SQL,对于同一个关联关系会维护两次,如下:
public static void main(String[] args)
{
ClassInfo classInfoNew;
ClassInfo classInfo;
Student studentNew;
Student student;
Configuration cfg = new Configuration();
cfg.configure();
ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
SessionFactory sf = cfg.buildSessionFactory(sr);
System.out.println("连接数据库");
Session session = sf.openSession();
Transaction transaction = session.beginTransaction();
try
{
classInfoNew = new ClassInfo();
classInfoNew.setName("测试Class");
classInfoNew.setNo("000");
studentNew = new Student();
studentNew.setName("测试Student");
studentNew.setNo("000");
studentNew.setSex("男");
studentNew.setBirthday(new Date(1993, 6, 11));
classInfoNew.getStudents().add(studentNew);
studentNew.setClassInfo(classInfoNew);
session.save(classInfoNew);//一定要先保存classInfo不然会报错,因为数据库约束了class_id为NOT NULL
session.save(studentNew);
student = (Student) session.get(Student.class, new Long(1));
student.setClassInfo(classInfoNew);//执行update维护关系
classInfoNew.getStudents().add(student);//执行update维护关系,update语句数受关联对象数影响,此处的update会有重复!
transaction.commit();
}
catch (Exception e)
{
transaction.rollback();
System.out.println("错误:" + e);
}
finally
{
session.close();
System.out.println("关闭数据库");
}
System.exit(0);
}
运行结果如下,注意最后的三条update语句:
连接数据库
Hibernate:
insert into tb_class (no, name) values (?, ?)Hibernate:
insert into tb_student (no, name, sex, birthday, class_id) values (?, ?, ?, ?, ?)Hibernate:
- ........ 省略若干获取关联对象的查询语句
Hibernate:
update tb_student set no=?, name=?, sex=?, birthday=?, class_id=? where id=?Hibernate:
update tb_student set class_id=? where id=?Hibernate:
update tb_student set class_id=? where id=?关闭数据库
重复执行多余的SQL语句会影响Java应用程序的性能,解决这一问题的办法是把bag元素的inverse属性设为true,该属性默认为false。inverse="true"表明在与的双向关联关系中,ClassInfo端的关联只是Student端关联的镜像,当Hibernate探测到对象ClassInfo和Student的属性都发生变化时,仅按照Student对象属性的变化更新数据库。
- <bag name="students" lazy="false" inverse="true">
<key column="class_id"/>
<one-to-many class="model.Student"/>
</bag>
设置后,再执行上面的程序,只会执行一条如下的SQL语句:
Hibernate:
update tb_student set no=?, name=?, sex=?, birthday=?, class_id=? where id=?
根据以上实验,可以得出这样的结论:
- 在映射一对多的双向关联关系时,应该在“one”放把bag元素的inverse属性设置为true,这样可以减少不必要的SQL执行,提高应用程序的性能。
- 在建立两个对象的双向关联时,应该同时修改关联两端对象的相应属性:student.setClassInfo(classInfoNew); classInfoNew.getStudents().add(student);
(3)级联操作(cascade)
当Hibernate保存一个临时对象时,在默认情况下它不会自动保存所关联的其它临时对象,所以会抛出TransientObjectException异常,如果希望保存Student对象时自动级联保存ClassInfo对象,可以把cascade的属性设置成save-update,配置如下:
- <many-to-one name="classInfo" column="class_id" class="model.ClassInfo" lazy="false" cascade="save-update"/>
当调用session.save(studentNew);时Hibernate会执行如下SQL:
连接数据库
Hibernate:
insert into tb_class (no, name) values (?, ?)Hibernate:
insert into tb_student (no, name, sex, birthday, class_id) values (?, ?, ?, ?, ?)关闭数据库
cascade属性的默认值为none,当Hibernate删除一个持久化对象时,不会自动删除与它关联的其他持久化对象。如果希望Hibernate删除ClassInfo对象时,自动删除和ClassInfo关联的Student对象,可以把cascade属性设为delete,配置如下:
<bag name="students" lazy="false" inverse="true" cascade="delete">
<key column="class_id"/>
<one-to-many class="model.Student" />
</bag>
当调用session.delete(classInfo);时,Hibernate会执行如下SQL:
Hibernate:
delete from tb_student where id=?Hibernate:
delete from tb_class where id=?
如果希望Hibernate自动删除不再和ClassInfo对象关联的Student对象,可以把cascade属性设置成all-delete-orphan,“all-delete-orphan”包含了“all”和“delete-orphan”的行为,配置如下:
<bag name="students" lazy="false" inverse="true" cascade="all-delete-orphan">
<key column="class_id"/>
<one-to-many class="model.Student" />
</bag>
5.建立一对多的双向自身关联关系
在实际的开发中包含一对多的关联关系的对象可能是同一个对象,例如某系统的区域信息表(tb_area),下面讲解如何映射一对多的自身关联,如下图:
新建tb_area表的语句如下,外键约束可选:
CREATE TABLE tb_area
(
id bigint NOT NULL auto_increment COMMENT 'ID',
name varchar(50) NOT NULL COMMENT '地区名称',
parent_id bigint COMMENT '所属区域ID',
PRIMARY KEY (id)
) COMMENT = '区域信息表';
-- 外键约束可续选
ALTER TABLE tb_area ADD CONSTRAINT fk_tb_area_1 FOREIGN KEY (parent_id) REFERENCES tb_area (id);
对应的实体类Area代码如下:
package model;
import java.util.Set;
public class Area
{
private Long id;
private String name;
private Area parentArea;
private Set<Area> childAreas = new HashSet<Area>();
// 省略setter、getter、toString...
}
映射文件(Area.hbm.xml),由于Area对象childAreas属性使用的Set类型的集合,所以相应的使用set元素配置映射,关于Java集合类型的映射将会在后面的文章中讲到,本例的配置如下:
<hibernate-mapping package="model">
<class name="Area" table="tb_area">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"/>
<many-to-one name="parentArea" column="parent_id" class="model.Area" cascade="save-update"/>
<set name="childAreas" inverse="true">
<key column="parent_id"/>
<one-to-many class="model.Area"/>
</set>
</class>
</hibernate-mapping>
测试代码以及控制台打印结果如下:
public static void main(String[] args)
{
Configuration cfg = new Configuration();
cfg.configure();
ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
SessionFactory sf = cfg.buildSessionFactory(sr);
System.out.println("连接数据库");
Session session = sf.openSession();
Transaction transaction = session.beginTransaction();
try
{
Area area1=new Area();
Area area2=new Area();
Area area3=new Area();
Area area4=new Area();
Area area5=new Area();
area1.setName("中国");
area2.setName("湖北省");
area3.setName("湖南省");
area4.setName("武汉市");
area5.setName("仙桃市");
area2.setParentArea(area1);
area3.setParentArea(area1);
area4.setParentArea(area2);
area5.setParentArea(area2);
session.save(area3);
session.save(area4);
session.save(area5);
transaction.commit();
}
catch (Exception e)
{
transaction.rollback();
System.out.println("错误:" + e);
}
finally
{
session.close();
System.out.println("关闭数据库");
}
System.exit(0);
}
连接数据库
Hibernate: insert into tb_area (name, parent_id) values (?, ?)
Hibernate: insert into tb_area (name, parent_id) values (?, ?)
Hibernate: insert into tb_area (name, parent_id) values (?, ?)
Hibernate: insert into tb_area (name, parent_id) values (?, ?)
Hibernate: insert into tb_area (name, parent_id) values (?, ?)
关闭数据库
由于配置了级联保存和更新(cascade="save-update"和inverse="true"),所以保存了5条数据。
6.改进持久化类
如果要建立地区中国与湖北省的关系,必须要调用下面的代码:
area1.setName("中国");
area2.setName("湖北省");
area2.setParentArea(area1);
area1.getChildAreas().add(area2);
为了简化管理对象之间的关联关系的编程代码,可以在Area类中增加addChildArea方法,代码如下:
public Area addChildArea(Area area)
{
if (area != null)
{
if (this.childAreas == null)
{
this.childAreas = new HashSet<Area>();
}
//删除原有的关系
if (area.getParentArea() != null)
{
area.getParentArea().getChildAreas().remove(area);
}
//设置当前关系
this.childAreas.add(area);
area.setParentArea(this);
}
return this;
}
使用此方法可以很方便的设置关联关系,如下代码:
area1.setName("中国");
area2.setName("湖北省");
area3.setName("湖南省");
area1.addChildArea(area2).addChildArea(area3);
7.一对多、多对一相关配置详细说明
(1)many-to-one节点配置说明
<many-to-one name="PropertyName"
access="field|property"
column="TableColumn"
class="ClassName"
property-ref="PropertyNameFromAssociatedClass"
foreign-key="foreign-key"
formula="arbitrary SQL expression"
update="true|false"
insert="true|false"
not-null="true|false"
unique="true|false"
unique-key="unique-key"
index="index_name"
not-found="exception|ignore"
outer-join="true|false"
fetch="join|select"
lazy="true|false"
cascade="all|none|save-update|delete"
optimistic-lock="true|false"
embed-xml="true|false"
entity-name="EntityName"
node="element-name"/>
如上展示了many-to-one节点常用的配置,是面对其配置进行详细的说明:
- name:实体类属性名。
- access:默认的实体类属性访问模式,取值为property表示访问getter、setter方法间接访问实体类字段,取值为field表示直接访问实体类字段(类成员变量)。
- column:对应的数据库字段名,此处的字段是外键字段。
- class:关联的类的名字,默认是通过反射得到属性类型。
- property-ref:指定关联类的一个属性,这个属性将会和本外键相对应。如果没有指定,会使用对方关联类的主键。
- foreign-key:关联的数据库外键名。
- formula:一个SQL表达式,定义了这个计算属性的值,计算属性没有和它对应的数据库字段。
- update:在update时是否含有此字段。
- insert:在insert时是否含有此字段。
- not-null:字段能否为空。
- unique:字段是否唯一。
- unique-key:为此字段创建唯一约束,属性值即为数据库唯一约束名,只影响自动生成的schema脚本。
- index:为此字段创建索引,属性值即为数据库索引名,只影响自动生成的schema脚本。
- not-found:指定外键引用的数据不存在时如何处理,ignore会将数据不存在作为关联到一个空对象(null)处理,默认为exception。
- outer-join:设置Hibernate是否使用外连接获取关联的数据,设置成true可以减少SQL语句的条数。
- fetch:参数指定了关联对象抓取的方式是select查询还是join查询,默认为select。fetch="join"等同于outer-join="true",fetch="select"等同于outer-join="false"。
- lazy:是否采用延迟加载策略。
- cascade:指明哪些操作会从父对象级联到关联的对象。
- optimistic-lock:指定这个属性在做更新时是否需要获得乐观锁定,默认为true。
- embed-xml:如果embed-xml="true",则对应于被关联实体或值类型的集合的XML树将直接嵌入拥有这些关联的实体的XML树中,默认值为true。
- entity-name:Hibernate3新增特性,用于动态模型(Dynamic Model)支持。Hibernate3允许一个类进行多次映射(前提是映射到不同的表)。
- node:配置说明。
(2)bag节点配置说明
<bag name="EntityClassName"
access="field|property|ClassName"
collection-type="collection-type"
schema="schema"
catalog="catalog"
check="arbitrary sql check condition"
table="TableName"
subselect="SQL expression"
where="arbitrary sql where condition"
optimistic-lock="false|true"
inverse="false|true"
fetch="join|select"
batch-size="5"
cascade="all|none|save-update|delete"
lazy="false|true"
mutable="false|true"
outer-join="false|true"
order-by="arbitrary sql order by condition"
embed-xml="false|true"
persister="PersisterClass"
node="element-name"/>
如上展示了bag节点常用的配置,是面对其配置进行详细的说明:
- name:实体类属性名。
- access:默认的实体类属性访问模式,取值为property表示访问getter、setter方法间接访问实体类字段,取值为field表示直接访问实体类字段(类成员变量)。
- collection-type:
- schema:数据库schema。
- catalog:数据库catalog。
- check:这是一个SQL表达式,用于为自动生成的schema添加多行约束检查。
- table:此集合里的实体类对应的数据库表名。
- subselect:一个SQL子查询,它将一个不可变并且只读的实体映射到一个数据库的子查询。
- where:一个SQL查询的where条件,获取这个关联类的对象时会一直增加这个条件。
- optimistic-lock:指定这个属性在做更新时是否需要获得乐观锁定,默认为true。
- inverse:当设置inverse="true"时,Hibernate将根此集合里的实体类类型的关联属性维护关联关系,默认值false。
- fetch:参数指定了关联对象抓取的方式是select查询还是join查询,默认为select。fetch="join"等同于outer-join="true",fetch="select"等同于outer-join="false"。
- batch-size:用于设置批次操作的SQL语句的数量,默认为1。
- cascade:指明哪些操作会从父对象级联到关联的对象。
- lazy:是否采用延迟加载策略。
- mutable:此集合里的实体类是否会发生改变,如果类实例对应的数据库表记录不会发生更新,可将其设为false,适用于单纯的Insert操作不使用update操作。
- outer-join:设置Hibernate是否使用外连接获取关联的数据,设置成true可以减少SQL语句的条数。
- order-by:一个SQL查询的order by条件,获取这个关联类的对象时会一直增加这个条件。
- embed-xml:如果embed-xml="true",则对应于被关联实体或值类型的集合的XML树将直接嵌入拥有这些关联的实体的XML树中,默认值为true。
- persister:指定持久化实现类,通过指定持久化类,我们可以实现自定义的持久化方法。持久化类为ClassPersister接口的实现。
- node:配置说明。
(3)one-to-many节点配置说明
<one-to-many class="ClassName"
not-found="exception|ignore"
embed-xml="true|false"
entity-name="EntityName"
node="element-name" />
如上展示了one-to-many节点常用的配置,是面对其配置进行详细的说明:
- class:关联的类的名字,默认是通过反射得到属性类型。
- not-found:指定外键引用的数据不存在时如何处理,ignore会将数据不存在作为关联到一个空对象(null)处理,默认为exception。
- embed-xml:如果embed-xml="true",则对应于被关联实体或值类型的集合的XML树将直接嵌入拥有这些关联的实体的XML树中,默认值为true。
- entity-name:Hibernate3新增特性,用于动态模型(Dynamic Model)支持。Hibernate3允许一个类进行多次映射(前提是映射到不同的表)。
- node:配置说明。
-------------------------------------------------------------------------------------------------------------------------------