在这个例子中,将考虑到表之间的一对一、一对多、多对多的情况。如图1所示。
图1 实体之间的映射关系
在上面的数据模型图中,Student是所有表的核心,它和Classes表是一对多的关系,和Course表是多对多的关系(通过Student_Course_Link表来链接),和Address表是一对一的关系。
通过分析,我们可以把上面的数据模型转换成如下的Java持久对象,如图2所示。
图2 持久对象之间的关系
可以看出,数据模型图和Java持久对象的类图有非常大的相似性,但是不完全相同。比如Classes表和Student表是一对多的关系;在类图中,两者仍然是一对多的关系,但是在Classes类中添加了一个student属性,属性的类型是java.util.Set,它表示Classes对象中包含的所有Student对象。
已经对数据模型经过了分析,现在就可以创建持久对象了。持久对象之间的关系由图2所示的类图指定。
相关代码:
Address.java:
package study;
/*
*在hibernate中代表了Address表的类。
*/
public class Address
{
/**属性,和Address表的字段一致**/
private String id;
private String zip;
private String state;
private String city;
private String street;
/**属性的访问方法,必须是公共的方法**/
public String getCity() {
return city;
}
public String getStreet() {
return street;
}
public String getId() {
return id;
}
public String getState() {
return state;
}
public String getZip() {
return zip;
}
public void setCity(String string) {
city = string;
}
public void setId(String string) {
id = string;
}
public void setState(String string) {
state = string;
}
public void setStreet(String street) {
this.street=street;
}
public void setZip(String string) {
zip = string;
}
}
Classes.java
package study;
import java.util.Set;
/**
*在hibernate中代表了Classes表的类。
*/
public class Classes
{
/**属性,和classes表的字段一致**/
private String id;
private String name;
/**和其它类之间的映射关系**/
private Set students;
/**属性的访问方法,必须是公共的方法**/
public void setId(String string) {
id = string;
}
public String getId() {
return id;
}
public void setName(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
/**操作和其它对象之间的关系**/
public void setStudents(Set stud)
{
this.students=stud;
}
public Set getStudents()
{
return this.students;
}
}
Course.java
package study;
import java.util.Set;
/**
*在hibernate中代表了Course表的类。
*/
public class Course
{
/**每个属性和表的一个字段对应**/
private String id;
private String name;
/**students表示course中的学生,在后面才会用到,暂时不管**/
private Set students;
/**属性的访问方法,必须是公共的方法**/
public void setId(String string) {
id = string;
}
public String getId() {
return id;
}
public void setName(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
/**操作和其它对象之间的关系**/
public void setStudents(Set stud)
{
this.students=stud;
}
public Set getStudents()
{
return this.students;
}
}
Student.java
package study;
import java.util.Set;
/**
*在hibernate中代表了Students表的类。
*/
public class Student
{
/**属性,和students表中的字段对应**/
private String id;
private String name;
/**和其它类之间的映射关系**/
private Set courses;
private Classes classes;
private Address address;
/**属性的访问方法,必须是公共的方法**/
public void setId(String string) {
id = string;
}
public String getId() {
return id;
}
public void setName(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
/**操作和其它对象之间的关系**/
public void setCourses(Set co)
{
this.courses=co;
}
public Set getCourses()
{
return this.courses;
}
public void setAddress(Address ad)
{
this.address=address;
}
public Address getAddress()
{
return this.address;
}
public void setClasses(Classes c)
{
this.classes=c;
}
public Classes getClasses()
{
return this.classes;
}
}
HibernateBase.java
package study;
import org.hibernate.*;
import org.hibernate.cfg.*;
import java.util.*;
import java.io.IOException;
import java.io.PrintWriter;
public abstract class HibernateBase
{
protected SessionFactory sessionFactory;//会话工厂,用于创建会话
protected Session session;//hibernate会话
protected Transaction transaction; //hiberante事务
public HibernateBase()throws HibernateException
{
this.initHibernate();
}
// 帮助方法
protected void initHibernate()
throws HibernateException {
// 装载配置,构造SessionFactory对象
sessionFactory = new Configuration().configure().buildSessionFactory();
}
/**
*开始一个hibernate事务
*/
protected void beginTransaction()
throws HibernateException {
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}
/**
*结束一个hibernate事务。
*/
protected void endTransaction(boolean commit)
throws HibernateException {
if (commit) {
transaction.commit();
} else {
//如果是只读的操作,不需要commit这个事务。
transaction.rollback();
}
session.close();
}
}
MapTestBean.java
package study;
import org.hibernate.*;
import org.hibernate.cfg.*;
import java.util.*;
/**
*测试持久对象的映射关系
*/
public class MapTestBean extends HibernateBase
{
public MapTestBean() throws HibernateException
{
super();
}
/**
*在数据库中添加数据
*/
public void addData(String studentId,String classesId,String coursesId)
throws HibernateException {
try
{
/**
*以下的代码添加了一个Student,同时为Student指定了
*Address、Courses和Classses。
*/
beginTransaction();
//创建一个Student对象 。
Student student = new Student();
student.setName("hellking2");
student.setId(studentId);
//创建一个Address对象。
Address addr=new Address();
addr.setCity("beijing");
addr.setState("bj");
addr.setStreet("tsinghua");
addr.setZip("100083");
addr.setId(student.getId());
//设置Student和address的关系。
student.setAddress(addr);
Set set=new HashSet();
set.add(student);
//创建一个course对象。
Course course=new Course ();
course.setId(coursesId);
course.setName("computer_jsp");
//设置course和student对象之间的关系。
course.setStudents(set);
//创建一个classes对象。
Classes cl=new Classes();
cl.setId(classesId);
cl.setName("engine power");
//设置某个classes对象包含的的students对象。
cl.setStudents(set);
//由于是双向的关系,student对象也需要设置一次。
student.setClasses(cl);
//保存创建的对象到session中。
session.save(cl);
session.save(course);
session.save(student);
session.save(addr);
//提交事务,使更改生效。
endTransaction(true);
}
catch(HibernateException e)
{
System.out.println("在添加数据时出错!");
e.printStackTrace();
throw e;
}
}
/**
*获得某个给定studentid的Student的地址信息
*/
public Address getAddress(String id) throws HibernateException
{
beginTransaction();
Student st=(Student)session.load(Student.class,id);
Address addr=(Address)session.load(Address.class,st.getId());
endTransaction(false);
return addr;
}
/**
*获得某个给定studentid的Student的所有课程
*/
public Set getCourses(String id)throws HibernateException
{
beginTransaction();
Student st=(Student)session.load(Student.class,id);
endTransaction(false);
return st.getCourses();
}
/**
*测试获得某个给定studentid的Student所属的Classes
*/
public Classes getClasses(String id)throws HibernateException
{
beginTransaction();
Student st=(Student)session.load(Student.class,id);
System.out.println(st.getClasses().getId());
endTransaction(false);
return st.getClasses();
}
/**
*删除和某个学生相关的所有信息
*(这里只是测试,我们暂且不说这种操作的意义何在)。
*/
public void delteStudent(String id)throws HibernateException
{
beginTransaction();
Student st=(Student)session.load(Student.class,id);
Address addr=(Address)session.load(Address.class,st.getId());
//删除address信息。
session.delete(addr);
//删除classes信息。
session.delete(st.getClasses());
/**
*逐个删除course。
*/
for(Iterator it=st.getCourses().iterator();it.hasNext();)
{
Course c=(Course)it.next();
session.delete(c);
}
//最后,删除student对象。
session.delete(st);
endTransaction(true);
}
}
Course.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="study.hibernate.Course"
table="Courses"
dynamic-update="false"
>
<id
name="id"
column="CourseId"
type="string"
unsaved-value="any"
>
<generator class="assigned"/>
</id>
<property
name="name"
type="string"
update="true"
insert="true"
column="Name"
/>
<set
name="students"
table="Student_Course_Link"
lazy="false"
inverse="false"
cascade="all"
sort="unsorted"
>
<key
column="CourseId"
/>
<many-to-many
class="study.hibernate.Student"
column="StudentId"
outer-join="auto"
/>
</set>
</class>
</hibernate-mapping>
Student.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="study.hibernate.Student"
table="Students"
dynamic-update="false"
>
<!– 描述ID字段–>
<id
name="id"
column="StudentId"
type="string"
unsaved-value="any" >
<generator class="assigned"/>
</id>
<!– 属性–>
<property
name="name"
type="string"
update="true"
insert="true"
column="Name"
/>
<!– 描述Student和Course多对多的关系–>
<set
name="courses"
table="Student_Course_Link"
lazy="false"
inverse="false"
cascade="all"
sort="unsorted"
>
<key
column="StudentId"
/>
<many-to-many
class="study.hibernate.Course"
column="CourseId"
outer-join="auto"
/>
</set>
<!– 描述Student和Classes之间多对一的关系–>
<many-to-one
name="classes"
class="study.hibernate.Classes"
cascade="none"
outer-join="auto"
update="true"
insert="true"
column="ClassesId"
/>
<!– 描述Student和Address之间一对一的关系–>
<one-to-one
name="address"
class="study.hibernate.Address"
cascade="none"
outer-join="auto"
constrained="false"
/>
</class>
</hibernate-mapping>
Classes.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="study.hibernate.Classes"
table="Classes"
dynamic-update="false"
>
<id
name="id"
column="ClassesId"
type="string"
unsaved-value="any"
>
<generator class="assigned"/>
</id>
<property
name="name"
type="string"
update="true"
insert="true"
column="Name"
/>
<set
name="students"
table="Students"
lazy="false"
inverse="false"
cascade="all"
sort="unsorted"
>
<key
column="ClassesId"
/>
<one-to-many
class="study.hibernate.Student"
/>
</set>
</class>
</hibernate-mapping>
hibernate.cfg.xml
<?xml version=’1.0′ encoding=’utf-8′?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:comp/env/jdbc/hibernate</property>
<property name="show_sql">false</property>
<property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
<!– Mapping files –>
<mapping resource="Address.hbm.xml"/>
<mapping resource="Student.hbm.xml"/>
<mapping resource="Classes.hbm.xml"/>
<mapping resource="Course.hbm.xml"/>
</session-factory>
</hibernate-configuration>
不错。。
对我帮助特别大。十分感谢。。。。
hbing —— 2007年04月19日 @10:00 am
先谢谢你了,我的QQ:19045962,我还有很多实际问题,希望你能帮我
skycliff —— 2007年08月26日 @7:36 pm
Thanks.
Sonic —— 2008年07月10日 @9:22 am