[标题]:[原]Hibernate集合映射
[时间]:2009-7-3
[摘要]:Hibernate中Set、List、Map、Array等集合的映射。
[关键字]:Hibernate,ORM,关联,集合,聚合,合成,composite,aggregation,持久化,映射,Abstract,List,Map,Array,Set,DAO,对象,Bag,组合,Bean,包含
[环境]:MyEclipse7,Hibernate3.2,MySQL5.1
[作者]:Winty (wintys@gmail.com) http://www.blogjava.net/wintys
[正文]:
Hibernate中包含关系的映射。包含关系包括聚合(Aggregation)、合成(Composite)关系。关联强度:合成>聚合>关联。
1、component映射
component映射在面向对象概念中是合成关系。
实体类:
public class Person {
......
private Name name;
......
}
public class Name {
private String firstName;
private String lastName;
......
}
配置文件:
<component name="name" class="wintys.hibernate.collection.entity.Name">
<property name="firstName" />
<property name="lastName" />
</component>
数据库表:
实体类没有单独映射为一个表,而是直接存于Person类对应的表中。
CREATE TABLE Person(
......
firstName VARCHAR(50),
lastName VARCHAR(50),
......
);
2、集合映射
Set、List、Map、Array等集合分别对应着java.util.Set、java.util.List、java.util.Map、数组。在持久化时,集合中的元素通过<element>或<composite-element>映射。
(1)、<element>对应Java中的基本数据类型(int、float等),还包括String。
实体类:
public class Person {
......
private Set<String> addresses;//集合里放的是String,所以用<element>映射
......
}
配置:(<key>表示PersonAddress的外键)
<set name="addresses" table="PersonAddress">
<key column="person_id" not-null="true"/>
<element column="addr" type="string" />
</set>
数据库表:
CREATE TABLE Person(
id INT(4) NOT NULL,
......
);
CREATE TABLE PersonAddress(
......
addr VARCHAR(200),
person_id INT(4), -- 外键
......
);
(2)、<composite-element>对应复合类型(用户自定义类型)。
实体类:
public class Person {
......
private Set<Email> emails;
......
}
public class Email {
private String userName;
private String hostName;
......
}
配置文件:
<set name="emails" table="PersonEmail">
<key column="person_id" not-null="true"/>
<composite-element class="wintys.hibernate.collection.entity.Email">
<property name="userName" />
<property name="hostName" />
</composite-element>
</set>
数据库表:
CREATE TABLE PersonEmail(
......
userName VARCHAR(100),
hostName VARCHAR(100),
person_id INT(4),
......
);
(3)、Set集合直接使用<set>标签进行映射,而List、Map、Array集合则需要在<list>、<map>、<array>中添加索引字段用于标明位置或key,当然在数据库中也要相应添加索引字段。
<list name="friends" table="PersonFriend">
<key column="person_id" not-null="true"/>
<index column="indexKey" />
<composite-element class="wintys.hibernate.collection.entity.Friend">
<property name="name" />
<property name="description" column="theDescription"/>
</composite-element>
</list>
<!-- map -->
<map name="relatives" table="PersonRelative">
<key column="person_id" not-null="true"/>
<index column="indexKey" type="string"/>
<composite-element class="wintys.hibernate.collection.entity.Relative">
<property name="name" />
<property name="description" column="theDescription"/>
</composite-element>
</map>
<!-- array -->
<array name="hobbies" table="PersonHobby">
<key column="person_id" not-null="true" />
<index column="indexKey"/>
<element column="value" type="string" />
</array>
总之,首先选择集合(如Set),再在集合映射中配置集合中到底存放的是什么类型的元素(如<element>)。
3、详细实例
(1)、实体类
【图:entity.jpg】
/src/wintys/hibernate/collection/entity/Person.java:
package wintys.hibernate.collection.entity;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Person
* @version 2009-07-03
* @author Winty (wintys@gmail.com) http://wintys.blogjava.net
*
*/
public class Person {
private int id;
private int age;
private Name name;//Person与Name是包含关系
private Set<String> addresses;
private Set<Email> emails;
private List<Friend> friends;
private Map<String , Relative> relatives;
private String[] hobbies;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
public Set<String> getAddresses() {
return addresses;
}
public void setAddresses(Set<String> addresses) {
this.addresses = addresses;
}
public Set<Email> getEmails() {
return emails;
}
public void setEmails(Set<Email> emails) {
this.emails = emails;
}
public List<Friend> getFriends() {
return friends;
}
public void setFriends(List<Friend> friends) {
this.friends = friends;
}
public Map<String, Relative> getRelatives() {
return relatives;
}
public void setRelatives(Map<String, Relative> relatives) {
this.relatives = relatives;
}
public String[] getHobbies() {
return hobbies;
}
public void setHobbies(String[] hobbies) {
this.hobbies = hobbies;
}
}
/src/wintys/hibernate/collection/entity/Name.java:
package wintys.hibernate.collection.entity;
/**
* 姓名
* @version 2009-07-03
* @author Winty (wintys@gmail.com)
*
*/
public class Name {
private String firstName;
private String lastName;
public Name(){
}
public Name(String firstName , String lastName){
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
/src/wintys/hibernate/collection/entity/Email.java:
package wintys.hibernate.collection.entity;
/**
* Email
* e-mail格式:userName@hostName
* @version 2009-07-03
* @author Winty (wintys@gmail.com)
*
*/
public class Email {
private String userName;
private String hostName;
public Email(){
}
public Email(String userName , String hostName){
this.userName = userName;
this.hostName = hostName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
}
/src/wintys/hibernate/collection/entity/Friend.java:
package wintys.hibernate.collection.entity;
/**
* 朋友
* @version 2009-07-03
* @author Winty (wintys@gmail.com)
*
*/
public class Friend {
private String name;
private String description;
public Friend(){
}
public Friend(String name , String description){
this.name = name;
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
/src/wintys/hibernate/collection/entity/Relative.java:
package wintys.hibernate.collection.entity;
/**
* 亲戚
* @version 2009-07-03
* @author Winty (wintys@gmail.com) http://wintys.blogjava.net
*
*/
public class Relative {
private String name;
private String description;
public Relative(){
}
public Relative(String name , String description){
this.name = name;
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
(2)数据库表:
【图:db1.jpg】
【图:db2.jpg】
-- author Winty (wintys@gmail.com) http://wintys.blogjava.net
-- 2009-07-03
USE db;
-- 先删除先前存在的表
DROP TABLE IF EXISTS PersonAddress;
DROP TABLE IF EXISTS PersonEmail;
DROP TABLE IF EXISTS PersonFriend;
DROP TABLE IF EXISTS PersonRelative;
DROP TABLE IF EXISTS PersonHobby;
DROP TABLE IF EXISTS Person;
CREATE TABLE Person(
id INT(4) NOT NULL,
age INT(4),
firstName VARCHAR(50),-- Name:firstName
lastName VARCHAR(50), -- Name:lastName
PRIMARY KEY(id)
);
CREATE TABLE PersonAddress(
id INT(4) AUTO_INCREMENT,
addr VARCHAR(200),
person_id INT(4), -- 外键
PRIMARY KEY(id),
CONSTRAINT FK_person_address FOREIGN KEY(person_id) REFERENCES Person(id)
);
CREATE TABLE PersonEmail(
id INT(4) AUTO_INCREMENT,
userName VARCHAR(100),-- email(userName@hostName) user
hostName VARCHAR(100),-- email(userName@hostName) host
person_id INT(4),
PRIMARY KEY(id),
CONSTRAINT FK_person_email FOREIGN KEY(person_id) REFERENCES Person(id)
);
CREATE TABLE PersonFriend(
id INT(4) AUTO_INCREMENT,
indexKey INT(4), -- List索引
name VARCHAR(50),-- friend name
theDescription VARCHAR(100),-- friend description
person_id INT(4),
PRIMARY KEY(id),
CONSTRAINT FK_person_friend FOREIGN KEY(person_id) REFERENCES Person(id)
);
-- 亲戚
CREATE TABLE PersonRelative(
id INT(4) AUTO_INCREMENT,
indexKey VARCHAR(50),-- Map Key
name VARCHAR(50),-- relative's name
theDescription VARCHAR(100),-- relative's description
person_id INT(4),
PRIMARY KEY(id),
CONSTRAINT FK_person_relative FOREIGN KEY(person_id) REFERENCES Person(id)
);
-- 爱好
CREATE TABLE PersonHobby(
id INT(4) AUTO_INCREMENT,
indexKey INT(4),-- Array index
value VARCHAR(100),
person_id INT(4),
PRIMARY KEY(id),
CONSTRAINT FK_person_hobby FOREIGN KEY(person_id) REFERENCES Person(id)
);
(3)、配置文件
/src/wintys/hibernate/collection/entity/Person.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
E-mail: wintys@gmail.com
Blog: http://wintys.blogjava.net
-->
<hibernate-mapping>
<class name="wintys.hibernate.collection.entity.Person" table="Person" catalog="db">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="increment"/>
</id>
<property name="age" type="java.lang.Integer" />
<!-- 包含关系映射 -->
<component name="name" class="wintys.hibernate.collection.entity.Name">
<property name="firstName" />
<property name="lastName" />
</component>
<!-- element -->
<set name="addresses" table="PersonAddress">
<key column="person_id" not-null="true"/>
<element column="addr" type="string" />
</set>
<!-- composite-element -->
<set name="emails" table="PersonEmail">
<key column="person_id" not-null="true"/>
<composite-element class="wintys.hibernate.collection.entity.Email">
<property name="userName" />
<property name="hostName" />
</composite-element>
</set>
<!-- list -->
<list name="friends" table="PersonFriend">
<key column="person_id" not-null="true"/>
<index column="indexKey" />
<composite-element class="wintys.hibernate.collection.entity.Friend">
<property name="name" />
<property name="description" column="theDescription"/>
</composite-element>
</list>
<!-- map -->
<map name="relatives" table="PersonRelative">
<key column="person_id" not-null="true"/>
<index column="indexKey" type="string"/>
<composite-element class="wintys.hibernate.collection.entity.Relative">
<property name="name" />
<property name="description" column="theDescription"/>
</composite-element>
</map>
<!-- array -->
<array name="hobbies" table="PersonHobby">
<key column="person_id" not-null="true" />
<index column="indexKey"/>
<element column="value" type="string" />
</array>
</class>
</hibernate-mapping>
/src/hibernate.cfg.xml:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="connection.username">root</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf-8
</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="myeclipse.connection.profile">MySQLDriver</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="show_sql">true</property>
<mapping resource="wintys/hibernate/collection/entity/Person.hbm.xml" />
</session-factory>
</hibernate-configuration>
4、测试
/src/wintys/hibernate/collection/dao/DAO.java:
package wintys.hibernate.collection.dao;
import java.util.List;
import org.hibernate.HibernateException;
import wintys.hibernate.collection.entity.Person;
public interface DAO {
public List<Person> doSelect(String selectHQL)throws HibernateException;
public boolean doInsert()throws HibernateException;
public boolean doDelete(Integer personId)throws HibernateException;
}
/src/wintys/hibernate/collection/dao/PersonDAO.java
package wintys.hibernate.collection.dao;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import wintys.hibernate.collection.entity.Email;
import wintys.hibernate.collection.entity.Friend;
import wintys.hibernate.collection.entity.Name;
import wintys.hibernate.collection.entity.Person;
import wintys.hibernate.collection.entity.Relative;
public class PersonDAO implements DAO {
@Override
public boolean doInsert() throws HibernateException {
Person person = new Person();
person.setAge(38);
person.setName(new Name("Bill" , "Gates"));
Set<String> addresses = new HashSet<String>();
addresses.add("New York USA");
addresses.add("中国 上海");
person.setAddresses(addresses);
Set<Email> emails = new HashSet<Email>();
emails.add(new Email("wintys" , "gmail.com"));
emails.add(new Email("abc" , "samplehost.com"));
emails.add(new Email("xyz" , "samplehost.com"));
person.setEmails(emails);
List<Friend> friends = new LinkedList<Friend>();
friends.add(new Friend("Jim" , "Best Friend."));
friends.add(new Friend("Smith" , "Classmate."));
person.setFriends(friends);
Map<String , Relative> relatives = new HashMap<String , Relative>();
relatives.put("uncle", new Relative("Sam" , "a lazy guy."));
relatives.put("brother", new Relative("Jimy" , "a good boy."));
person.setRelatives(relatives);
String[] hobbies = new String[3];
hobbies[0] = "Music";
hobbies[1] = "Classic Opera";
hobbies[2] = "Swimming";
person.setHobbies(hobbies);
Session session = null;
Transaction tc = null;
try{
session = HibernateUtil.getSession();
tc = session.beginTransaction();
session.save(person);
tc.commit();
}catch(HibernateException e){
try{
if(tc != null){
tc.rollback();
}
}catch(Exception ex){
System.err.println("Err:" + ex.getMessage());
}
System.err.println("Err:" + e.getMessage());
return false;
}finally{
HibernateUtil.closeSession();
}
return true;
}
@SuppressWarnings("unchecked")
@Override
public List<Person> doSelect(String selectHQL) throws HibernateException {
Session session = null;
List<Person> list = null;
try{
session= HibernateUtil.getSession();
Query query = session.createQuery(selectHQL);
list = query.list();
}catch(HibernateException e){
list = null;
System.err.println(e.getMessage());
}finally{
//因为要使用延迟加载,所以注释掉
//HibernateUtil.closeSession();
}
return list;
}
@Override
public boolean doDelete(Integer personId) throws HibernateException {
Session session = null;
Transaction tc = null;
try{
session = HibernateUtil.getSession();
tc = session.beginTransaction();
Person person = (Person)session.load(Person.class, personId);
session.delete(person);
tc.commit();
}catch(HibernateException e){
if(tc != null){
tc.rollback();
}
System.err.println("删除失败:" + e.getMessage());
return false;
}finally{
HibernateUtil.closeSession();
}
return true;
}
}
/src/wintys/hibernate/collection/dao/HibernateUtil.java:
package wintys.hibernate.collection.dao;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* 创建全局SessionFactory,通过ThreadLocal为每个线程提供不同的session
* @version 2009-05-20
* @author Winty
*/
public class HibernateUtil {
private static final SessionFactory sessionFactory;
private static final ThreadLocal<Session> threadLocal;
static{
try{
sessionFactory = new Configuration()
.configure()
.buildSessionFactory();
}catch(HibernateException e){
throw new ExceptionInInitializerError(e);
}
threadLocal = new ThreadLocal<Session>();
}
/**
* 获取session
* @return the current session
*/
public static Session getSession(){
Session session = threadLocal.get();
if(session == null){
session = sessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
/**
* 关闭当前session
*/
public static void closeSession(){
Session session = threadLocal.get();
if(session != null){
session.close();
}
threadLocal.set(null);
}
}
/src/wintys/hibernate/collection/Test.java
package wintys.hibernate.collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import wintys.hibernate.collection.dao.DAO;
import wintys.hibernate.collection.dao.PersonDAO;
import wintys.hibernate.collection.entity.Email;
import wintys.hibernate.collection.entity.Friend;
import wintys.hibernate.collection.entity.Name;
import wintys.hibernate.collection.entity.Person;
import wintys.hibernate.collection.entity.Relative;
/**
* Hibernate集合映射
* component、set、list、map、array
* @version 2009-07-03
* @author Winty (wintys@gmail.com) http://wintys.blogjava.net
*
*/
public class Test {
public static void main(String[] args){
DAO dao = new PersonDAO();
dao.doInsert();
//dao.doDelete(1);//级联删除
List<Person> persons = dao.doSelect("from Person");
printPerson(persons);
}
public static void printPerson(List<Person> persons){
Iterator<Person> it = persons.iterator();
while(it.hasNext()){
Person person = it.next();
int id = person.getId();
int age = person.getAge();
Name name = person.getName();
Set<String> addresses = person.getAddresses();
Set<Email> emails = person.getEmails();
List<Friend> friends = person.getFriends();
Map<String , Relative> relatives = person.getRelatives();
String[] hobbies = person.getHobbies();
System.out.println("id:" + id);
System.out.println("age:" + age);
printName(name);
printAddress(addresses);
printEmail(emails);
printFriend(friends);
printRelative(relatives);
printHobby(hobbies);
}
}
public static void printName(Name name){
System.out.print("firstName:" +name.getFirstName());
System.out.println(" lastName:" + name.getLastName());
}
public static void printAddress(Set<String> addresses){
Iterator<String> it = addresses.iterator();
while(it.hasNext()){
System.out.println(" addr:" + it.next());
}
}
public static void printEmail(Set<Email> emails){
Iterator<Email> it = emails.iterator();
while(it.hasNext()){
Email email = it.next();
System.out.println(" email:" + email.getUserName() + "@" + email.getHostName());
}
}
public static void printFriend(List<Friend> friends){
Iterator<Friend> it = friends.iterator();
while(it.hasNext()){
Friend friend = it.next();
System.out.println(" friend:" + friend.getName() + "," + friend.getDescription());
}
}
public static void printRelative(Map<String , Relative> relatives){
Set<String> keys = relatives.keySet();
Iterator<String> it = keys.iterator();
while(it.hasNext()){
String key = it.next();
Relative rt = relatives.get(key);
String name = rt.getName();
String desc = rt.getDescription();
System.out.println(" relative:" + key + ":" + name + "," + desc);
}
}
public static void printHobby(String[] hobbies){
for(String hobby : hobbies){
System.out.println(" hobby:" + hobby);
}
}
}
5、运行结果
【图:db1_result.jpg】
【图:db2_result.jpg】
Hibernate: select max(id) from Person
Hibernate: insert into db.Person (age, firstName, lastName, id) values (?, ?, ?, ?)
Hibernate: insert into PersonAddress (person_id, addr) values (?, ?)
Hibernate: insert into PersonAddress (person_id, addr) values (?, ?)
Hibernate: insert into PersonEmail (person_id, userName, hostName) values (?, ?, ?)
Hibernate: insert into PersonEmail (person_id, userName, hostName) values (?, ?, ?)
Hibernate: insert into PersonEmail (person_id, userName, hostName) values (?, ?, ?)
Hibernate: insert into PersonFriend (person_id, indexKey, name, theDescription) values (?, ?, ?, ?)
Hibernate: insert into PersonFriend (person_id, indexKey, name, theDescription) values (?, ?, ?, ?)
Hibernate: insert into PersonRelative (person_id, indexKey, name, theDescription) values (?, ?, ?, ?)
Hibernate: insert into PersonRelative (person_id, indexKey, name, theDescription) values (?, ?, ?, ?)
Hibernate: insert into PersonHobby (person_id, indexKey, value) values (?, ?, ?)
Hibernate: insert into PersonHobby (person_id, indexKey, value) values (?, ?, ?)
Hibernate: insert into PersonHobby (person_id, indexKey, value) values (?, ?, ?)
Hibernate: select person0_.id as id0_, person0_.age as age0_, person0_.firstName as firstName0_, person0_.lastName as lastName0_ from db.Person person0_
Hibernate: select hobbies0_.person_id as person1_0_, hobbies0_.value as value0_, hobbies0_.indexKey as indexKey0_ from PersonHobby hobbies0_ where hobbies0_.person_id=?
id:1
age:38
firstName:Bill lastName:Gates
Hibernate: select addresses0_.person_id as person1_0_, addresses0_.addr as addr0_ from PersonAddress addresses0_ where addresses0_.person_id=?
addr:New York USA
addr:中国 上海
Hibernate: select emails0_.person_id as person1_0_, emails0_.userName as userName0_, emails0_.hostName as hostName0_ from PersonEmail emails0_ where emails0_.person_id=?
email:wintys@gmail.com
email:abc@samplehost.com
email:xyz@samplehost.com
Hibernate: select friends0_.person_id as person1_0_, friends0_.name as name0_, friends0_.theDescription as theDescr3_0_, friends0_.indexKey as indexKey0_ from PersonFriend friends0_ where friends0_.person_id=?
friend:Jim,Best Friend.
friend:Smith,Classmate.
Hibernate: select relatives0_.person_id as person1_0_, relatives0_.name as name0_, relatives0_.theDescription as theDescr3_0_, relatives0_.indexKey as indexKey0_ from PersonRelative relatives0_ where relatives0_.person_id=?
relative:brother:Jimy,a good boy.
relative:uncle:Sam,a lazy guy.
hobby:Music
hobby:Classic Opera
hobby:Swimming
[参考资料]:
《J2EE项目实训 - Hibernate框架技术》: 清华大学出版社
[附件]:
源代码:
wintys_hibernate_collection.zip
原创作品,转载请注明出处。
作者:Winty (wintys@gmail.com)
博客:http://www.blogjava.net/wintys
posted on 2009-07-03 23:50
天堂露珠 阅读(796)
评论(0) 编辑 收藏 所属分类:
Hibernate