Learning Hibernate step by step - 04 多对一关联关系照射
Learning Hibernate step by step -- 04 多对一关联关系映射
Java对象有很多关联关系映射,如多对一、一对一、多对多等,在数据库中表之间有主外键关联,Java对象的关联关系如何与数据表形成映射呢?首先来看多对一的映射关系。
一、背景
1. 一所学校有很多班级(Group),一个班级有若干学生(Student),学生和班级之间的映射就是多对一的关联关系,如图所示:
[img][/img]
2. 数据库中分别存在t_group表和t_student表,分别对应班级和学生,t_student表有一个外键,引用t_group的id字段,ER关系如图所示:
[img][/img]
二、建立域对象
1. 先在项目中建立两个独立的域对象,Group和Student,两个对象包含基本的信息,先不对两个对象做关联。两外再分别建立两个对象的Dao对象,负责与数据库交互。
Persistent.java
Group.java
Student.java
GroupDao.java
StudentDao.java
三、建立映射文件
1. 分别建立Group和Student的映射文件
Group.hbm.xml
Student.hbm.xml
2. 在Hibernate配置文件中引入映射文件
另外,我们加入如下属性,让程序在加载配置文件是自动创建表
四、建立测试程序,分别建立Group对象和Student对象,分别保存到数据库中
观察控制台输出:
Group added successful!
Student added successful!
五、建立关联关系
1. 先建立对象的关联关系,在Student对象中增加Group对象的引用,代码如下(省略了setter和getter):
2. 在Student.hbm.xml中增加many-to-one的属性映射:
3. 修改测试代码,将Group对象加入Student中,运行程序,控制台输出成功信息
4. 在数据库中,我们发现t_student表多了一个字段group_id,这是外键,引用表t_group的id字段,由此,Hibernate自动实现了对象多对一关系到数据库表关联关系的映射。
六、总结
1. many-to-one属性的相关参数
解释如下:
(1). name: the name of the property.
(2). column (optional): the name of the foreign key column. This can also be specified by nested <column> element(s).
(3). class (optional - defaults to the property type determined by reflection): the name of the associated class.
(4). cascade (optional): specifies which operations should be cascaded from the parent object to the associated object.
(5). fetch (optional - defaults to select): chooses between outer-join fetching or sequential select fetching.
(6). update, insert (optional - defaults to true): specifies that the mapped columns should be included in SQL UPDATE and/or INSERT statements. Setting both to false allows a pure "derived" association whose value is initialized from another property that maps to the same column(s), or by a trigger or other application.
(7). property-ref (optional): the name of a property of the associated class that is joined to this foreign key. If not specified, the primary key of the associated class is used.
(8). access (optional - defaults to property): the strategy Hibernate uses for accessing the property value.
(9). unique (optional): enables the DDL generation of a unique constraint for the foreign-key column. By allowing this to be the target of a property-ref, you can make the association multiplicity one-to-one.
(10). not-null (optional): enables the DDL generation of a nullability constraint for the foreign key columns.
(11). optimistic-lock (optional - defaults to true): specifies that updates to this property do or do not require acquisition of the optimistic lock. In other words, it determines if a version increment should occur when this property is dirty.
(12). lazy (optional - defaults to proxy): by default, single point associations are proxied. lazy="no-proxy" specifies that the property should be fetched lazily when the instance variable is first accessed. This requires build-time bytecode instrumentation. lazy="false" specifies that the association will always be eagerly fetched.
(13). not-found (optional - defaults to exception): specifies how foreign keys that reference missing rows will be handled. ignore will treat a missing row as a null association.
(14). entity-name (optional): the entity name of the associated class.
(15). formula (optional): an SQL expression that defines the value for a computed foreign key.
参考文档:http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-manytoone
Java对象有很多关联关系映射,如多对一、一对一、多对多等,在数据库中表之间有主外键关联,Java对象的关联关系如何与数据表形成映射呢?首先来看多对一的映射关系。
一、背景
1. 一所学校有很多班级(Group),一个班级有若干学生(Student),学生和班级之间的映射就是多对一的关联关系,如图所示:
[img][/img]
2. 数据库中分别存在t_group表和t_student表,分别对应班级和学生,t_student表有一个外键,引用t_group的id字段,ER关系如图所示:
[img][/img]
二、建立域对象
1. 先在项目中建立两个独立的域对象,Group和Student,两个对象包含基本的信息,先不对两个对象做关联。两外再分别建立两个对象的Dao对象,负责与数据库交互。
Persistent.java
public class Persistent implements Serializable { private static final long serialVersionUID = 1L; private long id; public long getId() { return id; } public void setId(long id) { this.id = id; } }
Group.java
public class Group extends Persistent { private static final long serialVersionUID = 1L; String grpName; public String getGrpName() { return grpName; } public void setGrpName(String grpName) { this.grpName = grpName; } }
Student.java
public class Student extends Persistent { private static final long serialVersionUID = 1L; private String studNo; private String studName; private String studSex; public String getStudNo() { return studNo; } public void setStudNo(String studNo) { this.studNo = studNo; } public String getStudName() { return studName; } public void setStudName(String studName) { this.studName = studName; } public String getStudSex() { return studSex; } public void setStudSex(String studSex) { this.studSex = studSex; } }
GroupDao.java
public class GroupDao { public long saveGroup(Object obj) { Session session = HibernateUtil.getSessionFactory().openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Long retId = (Long)session.save(obj); tx.commit(); return retId.longValue(); } catch (Exception e) { if (tx != null) { tx.rollback(); } // DO NOT swallow the Exception in actual projects. // throw e; e.printStackTrace(); return 0L; } finally { session.close(); } } }
StudentDao.java
public class StudentDao { public long saveStudent(Object obj) { Session session = HibernateUtil.getSessionFactory().openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Long retId = (Long)session.save(obj); tx.commit(); return retId.intValue(); } catch (Exception e) { if (tx != null) { tx.rollback(); } // DO NOT swallow the Exception in actual projects. // throw e; e.printStackTrace(); return 0L; } finally { session.close(); } } }
三、建立映射文件
1. 分别建立Group和Student的映射文件
Group.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 package="com.foobar.domain"> <class name="Group" table="`T_Group`"> <comment>Groups infomation.</comment> <id name="id"> <generator class="native"/> </id> <property name="grpName" not-null="true" column="`grp_name`"/> </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 package="com.foobar.domain"> <class name="Student" table="`T_Student`"> <comment>Students infomation.</comment> <id name="id"> <generator class="native"/> </id> <property name="studName" length="15" column="`stud_name`"/> <property name="studSex" not-null="true" length="1" column="`stud_sex`"/> <many-to-one name="group" column="`group_id`"/> </class> </hibernate-mapping>
2. 在Hibernate配置文件中引入映射文件
... <mapping resource="com/foobar/conf/hbm/Group.hbm.xml"/> <mapping resource="com/foobar/conf/hbm/Student.hbm.xml"/> ...
另外,我们加入如下属性,让程序在加载配置文件是自动创建表
<!-- mapping与ddl之间的关系--> <property name="hibernate.hbm2ddl.auto">create</property>
四、建立测试程序,分别建立Group对象和Student对象,分别保存到数据库中
public class SchoolMgt { public static void main(String[] args) { GroupDao grpDao = new GroupDao(); Group grp = new Group(); StudentDao studDao = new StudentDao(); Student stud = new Student(); grp.setGrpName("Group A"); if(grpDao.saveGroup(grp) != 0) { System.out.println("Group added successful!"); } stud.setStudName("Zhangsan"); stud.setStudNo("0001001"); stud.setStudSex("F"); if(studDao.saveStudent(stud) != 0) { System.out.println("Student added successful!"); } } }
观察控制台输出:
Group added successful!
Student added successful!
五、建立关联关系
1. 先建立对象的关联关系,在Student对象中增加Group对象的引用,代码如下(省略了setter和getter):
private Group group; // setter and getter
2. 在Student.hbm.xml中增加many-to-one的属性映射:
<many-to-one name="group" column="`group_id`"/>
3. 修改测试代码,将Group对象加入Student中,运行程序,控制台输出成功信息
... stud.setGroup(grp); ...
4. 在数据库中,我们发现t_student表多了一个字段group_id,这是外键,引用表t_group的id字段,由此,Hibernate自动实现了对象多对一关系到数据库表关联关系的映射。
六、总结
1. many-to-one属性的相关参数
<many-to-one name="propertyName" (1) column="column_name" (2) class="ClassName" (3) cascade="cascade_style" (4) fetch="join|select" (5) update="true|false" (6) insert="true|false" (6) property-ref="propertyNameFromAssociatedClass" (7) access="field|property|ClassName" (8) unique="true|false" (9) not-null="true|false" (10) optimistic-lock="true|false" (11) lazy="proxy|no-proxy|false" (12) not-found="ignore|exception" (13) entity-name="EntityName" (14) formula="arbitrary SQL expression" (15) node="element-name|@attribute-name|element/@attribute|." embed-xml="true|false" index="index_name" unique_key="unique_key_id" foreign-key="foreign_key_name" />
解释如下:
(1). name: the name of the property.
(2). column (optional): the name of the foreign key column. This can also be specified by nested <column> element(s).
(3). class (optional - defaults to the property type determined by reflection): the name of the associated class.
(4). cascade (optional): specifies which operations should be cascaded from the parent object to the associated object.
(5). fetch (optional - defaults to select): chooses between outer-join fetching or sequential select fetching.
(6). update, insert (optional - defaults to true): specifies that the mapped columns should be included in SQL UPDATE and/or INSERT statements. Setting both to false allows a pure "derived" association whose value is initialized from another property that maps to the same column(s), or by a trigger or other application.
(7). property-ref (optional): the name of a property of the associated class that is joined to this foreign key. If not specified, the primary key of the associated class is used.
(8). access (optional - defaults to property): the strategy Hibernate uses for accessing the property value.
(9). unique (optional): enables the DDL generation of a unique constraint for the foreign-key column. By allowing this to be the target of a property-ref, you can make the association multiplicity one-to-one.
(10). not-null (optional): enables the DDL generation of a nullability constraint for the foreign key columns.
(11). optimistic-lock (optional - defaults to true): specifies that updates to this property do or do not require acquisition of the optimistic lock. In other words, it determines if a version increment should occur when this property is dirty.
(12). lazy (optional - defaults to proxy): by default, single point associations are proxied. lazy="no-proxy" specifies that the property should be fetched lazily when the instance variable is first accessed. This requires build-time bytecode instrumentation. lazy="false" specifies that the association will always be eagerly fetched.
(13). not-found (optional - defaults to exception): specifies how foreign keys that reference missing rows will be handled. ignore will treat a missing row as a null association.
(14). entity-name (optional): the entity name of the associated class.
(15). formula (optional): an SQL expression that defines the value for a computed foreign key.
参考文档:http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-manytoone