【复合主键映射】
一、映射原理:
复合主键的使用其实很简单,但是需要注意对象需要被拆分,主键自己需要一个类并且该类需要实现java.io.Serializable接口,其它的属性再重新生成新类,并且类的属性中要有主键类的对象,相应的只需要一个配置文件,在映射文件中使用<composite-id>指明主键,并指明主键的属性。
二、代码实践
以学生成绩为例,学生学号和课程号组成复合主键。
1.StudentCoursePK.java
封装主键属性,StudentCoursePK类是从StudentCourse类中分离出来的,包含了基本的主键属性,并且需要实现接口Serializable,该类是要映射到配置文件中<composite-id>标签中要指定该类,代码如下:
package com.bjpowernode.hibernate;
import java.io.Serializable;
public class StudentCoursePK implements Serializable {
//学号
private int studentID;
//课程号
private int courseID;
// get和set略
}
2.StudentCourse.java
package com.bjpowernode.hibernate;
import java.util.Date;
public class StudentCourse {
private StudentCoursePK studentCoursePK;
// 开始日期
private Date beginDate;
// 结束日期
private Date endDate;
// get和set略
}
3.映射文件StudentCourse.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="com.bjpowernode.hibernate.StudentCourse" table="t_student_course">
<composite-id name="studentCoursePK">
<key-property name="studentID"/>
<key-property name="courseID"/>
</composite-id>
<property name="beginDate" type="date"/>
<property name="endDate" type="date"/>
</class>
</hibernate-mapping>
三、注意
加载方法会和之前的加载有一丢丢不同,因为在该表中主键是复合属性,所以需要创建一个类。在加载数据时需要创建主键对象,此时的主键就是一个对象,更需要为对象的属性赋值,这样才能获取对象,具体如下
public void testLoad() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//构造复合主键对象
StudentCoursePK studentCoursePK = new StudentCoursePK();
studentCoursePK.setStudentID(2012100);
studentCoursePK.setCourseID(12021);
StudentCourse fiscalYearPeriod = (StudentCourse)session.load(StudentCourse.class, studentCoursePK);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
【Component映射】
一、需求
假如有两张表分别表示两类人User表和Employee表,前者是使用系统的用户,后者是公司的员工。员工和用户有相同的信息(email、address、ZipCode、contactTel),所以将公共部分提取出来,用以达到复用。
二、代码实践
1、实体映射类
User.java
package com.bjpowernode.hibernate;
public class User {
private int id;
private String name;
private Contact userContact;
// get和set略
}
Employee.java
package com.bjpowernode.hibernate;
public class Employee {
private int id;
private String name;
private Contact employeeContact;
// get和set略
}
Contact.java
package com.bjpowernode.hibernate;
public class Contact {
private String email;
private String address;
private String zipCode;
private String contactTel;
// get和set略
}
2、映射文件
User.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="com.bjpowernode.hibernate.User" table="t_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<component name="userContact">
<property name="email"/>
<property name="address"/>
<property name="zipCode"/>
<property name="contactTel"/>
</component>
</class>
</hibernate-mapping>
Employee.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="com.bjpowernode.hibernate.Employee" table="t_emplyee">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<component name="employeeContact">
<property name="email"/>
<property name="address"/>
<property name="zipCode"/>
<property name="contactTel"/>
</component>
</class>
</hibernate-mapping>
三、说明
1、在hibernate中Component映射采用<component>标签即可
2、Component是某个实体的逻辑组成部分,它与实体类的主要差别在于,它没有oid
Component在DDD中成为值类
3、采用Component的好处:实现对象模型的细粒度划分,复用率高,含义明确,层次分明
4、Component映射的添加数据
public void testSave() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//建立User实体类
User user = new User();
user.setName("张三");
//建立Contact值类,值类通常从属于实体类
Contact userContact = new Contact();
userContact.setEmail("email");
userContact.setAddress("address");
userContact.setZipCode("zipCode");
userContact.setContactTel("contactTel");
user.setUserContact(userContact);
session.save(user);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
【集合映射】
Hibernate的集合映射主要是介绍一下几种集合类型的映射:map、set、list、array。具体如下:
1、CollectionMapping.java
package com.bjpowernode.hibernate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@SuppressWarnings("unchecked")
public class CollectionMapping {
private int id;
private String name;
// set是无序的
private Set setValues = new HashSet();
// List是有序的
private List listValues = new ArrayList();
private String[] arrayValues;
private Map mapValues;
// get和set略
}
2、配置文件
<?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="com.bjpowernode.hibernate.CollectionMapping" table="t_collection_mapping">
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<!-- set标签来表示set集合映射:name属性表示customer对象中关系集合的属性名。 -->
<set name="setValues" table="t_set_values">
<key column="set_id" />
<element type="string" column="set_value" not-null="true" />
</set>
<!-- list标签来表示list集合映射 :List集合是有顺序的,list的顺序将表现在customer_index列上,其余设置与set类似(list映射总inverse中的值不能设置为true) -->
<list name="listValues" table="t_list_values">
<key column="list_id" />
<list-index column="list_index" />
<element type="string" column="list_value" />
</list>
<array name="arrayValues" table="t_array_values">
<key column="array_id" />
<list-index column="array_index" />
<element type="string" column="array_value" />
</array>
<!-- map标签来表示map集合映射:map中index标签表示map集合中的key值 -->
<map name="mapValues" table="t_map_values">
<key column="map_id" />
<map-key type="string" column="map_key" />
<element type="string" column="map_value" />
</map>
</class>
</hibernate-mapping>