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

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`"/>
</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.
参考文档:[url]http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-manytoone[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值