虽然烧退了,但是今天还是感到不舒服……
今天netmeeting还是不好用……怎么偏偏赶上我不舒服的这两天出问题呢……
今天讲关系映射。
集合里面塞的是实体的时候就是关系映射了。
关系主要有以下几种:1、一对一关系2、一对多关系3、多对一关系4、多对多关系除多对多关系需要关系表来反映外,其余都是直接通过外键来体现的
关系是有方向的,单向的关系是指从实体A能得到与其相关联另外一个实体B,但从实体B不能得到实体A例如,如果老师和课程之间是一对多的关系,并且通过一个老师能够知道他所讲的全部课程,但不能通过课程知道任课老师,这种关系就是单向的双向的关系是从关系中的任意一个角色都能得到另一实体
Hibernate中定义关联关系的要点:1、关联一方持有关联对象,通常是以属性的方式保存在对象中。两个实体,老师和学生,老师的属性中必须有个属性持有学生,学生也要有个属性持有老师。2、在映射文件中,使用one-to-one、one-to-many、many-to-one、many-to-many定义映射关系。3、对于one-to-many、many-to-many需要使用集合持有。在one的那一方肯定持有集合,many-to-many是在两方都要持有集合。
多对一关系中,当前对象持有外键。通过持有外键找到与之对应的对象。因此,在多对一关系中,当前对象包含一个与之关联的对象,这个对象以属性的方式存在对象中。例如,单元(Unit)和楼房(Buiding)之间就是多对一关系。一幢楼可以包括多个单元,单元只对应一幢楼
多的一方持有外键,指向主表的主键。
更通用的情况是使用many-to-one,如:<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <many-to-one name="address" column="addressId" not-null="true"/></class><class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id></class>
Person是多的一方,Address是一的一方。==========================================================================新建工程relation,加入jar包和驱动程序
在数据库中建表:teachers表:id、name、age(Integer类型)students表:id、name、scores(Integer类型)、tea_id
建立两个实体:在此之前,将昨天的配置文件拷贝过来。自己写的时候最好是重写配置文件,加深印象。
package vopublic class Student{ private int id ; private String name; private int scores; private Teacher teacher ;//学生是多的一方,要持有老师的对象 //加入getter和setter方法
}
package vo
public class Teacher{ private int id ; private String name ; private int age ;}
Student.hbm.xml:<hibernate-mapping package="vo"> //加入包名 <class name="Student" table="students">//上面加入了包名,所以这里name不用写类的全名。 <id name="id" column="id"> //这里如果column和name重名的话,column其实是可以忽略的! <generator class="identity" /> </id> <property name="name" column"name" /> <property name="scores" />//由于数据库中也有字段height,所以这里column可以省略。 //因为many开头,仅代表当前的Student类中持有外键,并不说明Student类一定是多的一方! <many-to-one name="teacher" column="tea_id" class="Teacher"/> //上面的这个class="Teacher"可以省略! </class>
<class name="Teacher" table="teachers"> <id name="id"> <generator class="identity" /> </id>
<property name="name" /> <property name="age" /> </class></hibernate-mapping>
public class Demo{ public static void main(String[] args) { SessionFactory factory = new Configuration().addClass(Student.class) .configure() .buildSessionFactory(); //这里不能再addClass(Teacher.class),因为我们的映射文件是Student.hbm.xml Teacher tea = new Teacher() ; Student stu = new Student() ; tea.setAge(30); tea.setName("df");
stu.setName("yuanbin"); stu.setScores(90); stu.setTeacher(tea);
Session session = factory.getCurrentSession();
session.beginTransaction(); session.save(tea); //一定要先保存老师,再保存学生。 session.save(stu);
//Student stu1 = (Student) session.get(Student.class,new Integer(2)) ; //System.out.println(stu1.getTeacher().getName()); //上面那两条注释的语句就是找到id为2的学员的老师的名字! session.getTransaction().commit();
session.close(); factory.close(); }}
===========================================================================
一对一关系有三种实现方式:一是通过外键方式实现,即当前对象持有关联对象的外键;二是通过主键方式实现,即当前对象的主键即是主键也是外键,也就是说当前对象的主键和与之相关联对象的主键是相同的。三是通过关系表实现,即关联双方都以外键的形式存储在关系表中,通过关系表反映一对一的关系,这种方式很少使用
从设计的角度来看,第三种是最好的,但是在实际应用中第一种方式用的是最多的。
先来看外键方式
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> //谁持有外键谁就使用many-to-one! <many-to-one name="address" column="addressId" unique="true" not-null="true"/></class><class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id></class>
在关联的另一端如果也要持有对象,应该写成:<class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <one-to-one name="owner" class="Person" property-ref="addressId"/></class>
package vopublic class Student{ private int id ; private String name; private int scores; private Teacher teacher ;//学生是多的一方,要持有老师的对象 //加入getter和setter方法
}
package vo
public class Teacher{ private int id ; private String name ; private int age ;
private Student student ;}
Student.hbm.xml:<hibernate-mapping package="vo"> //加入包名 <class name="Student" table="students">//上面加入了包名,所以这里name不用写类的全名。 <id name="id" column="id"> //这里如果column和name重名的话,column其实是可以忽略的! <generator class="identity" /> </id> <property name="name" column"name" /> <property name="scores" />//由于数据库中也有字段height,所以这里column可以省略。 //因为many开头,仅代表当前的Student类中持有外键,并不说明Student类一定是多的一方! <many-to-one name="teacher" column="tea_id" class="Teacher" /> //上面的这个class="Teacher"可以省略! </class>
<class name="Teacher" table="teachers"> <id name="id"> <generator class="identity" /> </id>
<property name="name" /> <property name="age" /> //因为one开头,所以没有外键! <one-to-one name="student" property-ref="teacher" class="Student" unique="true"/> //上面这个class可以不写!!student对应的是Teacher类中的一个属性,是拿老师的主键对应学生表的外键 //由于是实体teacher对应外键,所以property-ref对应的是teacher </class></hibernate-mapping>
这个是老师写的配置文件:<?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"><hibernate-mapping package="vo">
<class name="Student" table="students"> <id name="id" column="id"> <generator class="identity" /> </id> <property name="name" /> <property name="scores" /> <many-to-one name="teacher" column="tea_id" lazy="no-proxy" unique="true"/> </class> <class name="Teacher" table="teachers"> <id name="id"> <generator class="identity" /> </id> <property name="name" /> <property name="age" /> <one-to-one name="student" property-ref="teacher" /> </class></hibernate-mapping>
================================================================================
主键方式:
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id></class><class name="Address"> <id name="id" column="personId"> <generator class="foreign"> <param name="property">person</param> </generator> </id> <one-to-one name="person" constrained="true"/> //上面这个constrained设置为true可以加也可以不加的!</class>//Person是主动的一方,Address是被动的一方,Address必须知道Person//的主键于是foreign的主键生成器需要一个参数,参数将Person的主键取出//作为Address的主键!
如果定义双向一对一,则<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <one-to-one name="address"/></class><class name="Address"> <id name="id" column="personId"> <generator class="foreign"> <param name="property">person</param> </generator> </id> <one-to-one name="person" constrained="true"/></class>
----------------------------------------------------------------
<hibernate-mapping package="vo"> //加入包名 <class name="Student" table="students">//上面加入了包名,所以这里name不用写类的全名。 <id name="id" column="id"> //这里如果column和name重名的话,column其实是可以忽略的! <generator class="foreign" > <param name="property">teacher</param> </generator> </id> <property name="name" column"name" /> <property name="scores" />//由于数据库中也有字段height,所以这里column可以省略。 <one-to-one name="teacher" /> //上面的这个class="Teacher"可以省略! </class>
<class name="Teacher" table="teachers"> <id name="id"> <generator class="identity" /> </id>
<property name="name" /> <property name="age" /> //因为one开头,所以没有外键! <one-to-one name="student" /> //上面这个class可以不写!!student对应的是Teacher类中的一个属性,是拿老师的主键对应学生表的外键 //由于是实体teacher对应外键,所以property-ref对应的是teacher </class></hibernate-mapping>===========================================================================================
下午课程开始:
一对一关系:使用关系表方式。关系表中放两个主键,对于一个关系表来说,到关系表里面找外键去对类的主键,然后用另外一个外键去对应实体。
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <join table="PersonAddress“ optional="true"> <key column="personId“ unique="true"/> <many-to-one name="address“ column="addressId“ not-null="true“ unique="true"/> </join> //join映射类里面的一个属性。关系表里面持有外键。</class><class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id></class>
如果是双向的话:
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <join table="PrsnAddr" optional="true"> <key column="personId“ unique="true"/> <many-to-one name="address“ column="addrId" not-null="true“ unique="true"/> </join></class><class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <join table="PrsnAddr" optional="true" inverse="true"> <key column="addrId" unique="true"/> <many-to-one name="person" column="personId" not-null="true" unique="true"/> </join></class>----------------------------------------------------------建立一个老师和学生之间的关系表stu_tea:
stu_id integer类型tea_id integer类型
<?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"><hibernate-mapping package="vo">
<class name="Student" table="students"> <id name="id" column="id"> <generator class="identity" /> </id> <property name="name" /> <property name="scores" /> <join table="tea_stu" optional="true"> <key column="stu_id" /> <many-to-one name="teacher" column="tea_id" /> //学生里面持有老师 </join> </class> <class name="Teacher" table="teachers"> <id name="id"> <generator class="identity" /> </id> <property name="name" /> <property name="age" /> <join table="tea_stu" inverse="true"> //一般来说,如果是双向的关系,其中的一个关系表要设置inverse属性,另一个关系表 //设置optional属性,但是不可在两个关系表中都设置inverse属性。 <key column="tea_id" /> <many-to-one name="student" column="stu_id" /> </join>
</class></hibernate-mapping>
老师写的配置文件:<?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"><hibernate-mapping package="vo">
<class name="Student" table="students"> <id name="id" column="id"> <generator class="identity" /> </id> <property name="name" /> <property name="scores" /> <join table="stu_tea" optional="true"> <key column="stu_id" /> <many-to-one name="teacher" column="tea_id" />//name是属性名 </join> </class> <class name="Teacher" table="teachers"> <id name="id"> <generator class="identity" /> </id> <property name="name" /> <property name="age" /> <join table="stu_tea" optional="true" inverse="true"> <key column="tea_id" /> <many-to-one name="student" column="stu_id" /> </join> </class></hibernate-mapping>
==================================================================================一对多关系:一对多关系有两种方式实现:一是通过外键方式实现,“一”的角色不持有外键,外键被多的一方持有。Hibernate不鼓励使用 这种方式实现一对多关系。二是通过关系表实现,外键被关系表持有,每一条对应关系都必须在关系表中注册。
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses"> <key column="personId" not-null="true"/> <one-to-many class="Address"/> </set></class><class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id></class>
双向:<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses"> <key column="personId" not-null="true"/> <one-to-many class="Address"/> </set></class><class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <many-to-one name=“person” column=“personId”/></class>
-----------------------------------------------------------
package vopublic class Student{ private int id ; private String name; private int scores; private Teacher teacher ; //加入getter和setter方法
}
package vo
public class Teacher{ private int id ; private String name ; private int age ;
private Set students = new HashSet() ;}
<?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"><hibernate-mapping package="vo">
<class name="Student" table="students"> <id name="id" column="id"> <generator class="identity" /> </id> <property name="name" /> <property name="scores" /> <many-to-one name="teacher" column="tea_id" /> </class> <class name="Teacher" table="teachers"> <id name="id"> <generator class="identity" /> </id> <property name="name" /> <property name="age" /> <set name="students"> <key column="tea_id" /> <one-to-many class="Student" /> </set> </class></hibernate-mapping>----------------------------session.save(stu);tea.getStudents().add(stu);session.save(tea);
----------------------------session.save(stu);Teacher t = (Teacher)session.load(Teacher.class,new Integer(11));t.getStudents().add(stu);t.getStudents().add(stu);
-----------------------------------------------------------------关系表实现一对多关系:
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses" table="PersonAddress"> <key column="personId"/> <many-to-many column="addressId" unique="true" class="Address"/> </set></class><class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id></class>
双向:<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses" table="PersonAddress"> <key column="personId"/> <many-to-many column="addressId" unique="true" class="Address"/> </set></class><class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <join table="PersonAddress" inverse="true" optional="true"> <key column="addressId"/> <many-to-one name="person" column="personId" not-null="true"/> </join></class>
-----------------------------------
<?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"><hibernate-mapping package="vo">
<class name="Student" table="students"> <id name="id" column="id"> <generator class="identity" /> </id> <property name="name" /> <property name="scores" /> <join table="stu_tea" inverse="true"> <key column="stu_id" /> //拿stu_tea的外键去对Student的主键 <many-to-one name="teacher" column="tea_id"/> </join> </class> <class name="Teacher" table="teachers"> <id name="id"> <generator class="identity" /> </id> <property name="name" /> <property name="age" /> <set name="students" table="stu_tea"> <key column="tea_id" /> <many-to-many class="Student" column="stu_id"/> </set> </class></hibernate-mapping>
============================================================
多对多关系:两边都持有集合,老师里面有学生集合、学生里面也有老师集合。也就是双方配置的时候都应该有set,set可以对上关系表,而且都是many-to-many
多对多只能通过关系表的形式实现,每一条关系都必须在关系表中注册。关系双方都不持有外键,但均持有一个集合属性,代表与之关联的关系另一角色。
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses" table="PersonAddress"> <key column="personId"/> <many-to-many column="addressId" class="Address"/> </set></class><class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <set name="people" inverse="true" table="PersonAddress"> <key column="addressId"/> <many-to-many column="personId" class="Person"/> </set></class>
==============================================================================简单总结一下:一对一三种,一对多两种,多对多一种。