常用的Hibernate的映射与数据库表的关系(二)
2011-06-05 12:29
337 查看
上篇文章介绍了下多对一的关系关联映射,这次来介绍下其他的几种映射。
首先,介绍下一对多。有人会有疑问:一对多和多对一不是一样的吗?下面我们接着用学生和班级的例子继续来说明下。一对多表示:控制方在一的这一端,比如可以查找属于同一个班级下的所有的学生。这个该怎么实现,试想下你要查找班级下的学生你的Classes类下面就必须要有Student类对象的这个属性字段。private Set<Student> students;利用这个属性来加载属于当前班级下的所有的学生。其他的属性字段同一对多的一样。项目结构图如下:
![](http://hi.csdn.net/attachment/201106/5/0_1307245060m6mg.gif)
当前使用的是一对多的映射,配置一般在一的一端。配置如下:
注意下当前我们使用的不再是<property>而是<set>标签。set标签中name和property的name一样表示利用Classes这个类的students属性来生成一个字段,该字段名字由<key>来指定也就是cid,并且该字段为Student的外键(由<one-to-many>来指定)。
运行下,同样的会产生如下的代码:
drop table if exists t_classes
drop table if exists t_student
create table t_classes (cid integer not null auto_increment, cname varchar(50), primary key (cid))
create table t_student (sid integer not null auto_increment, sname varchar(50), cid integer, primary key (sid))
alter table t_student add index FK4B907570D95D9B22 (cid), add constraint FK4B907570D95D9B22 foreign key (cid) references t_classes (cid)
配置的这个地方有两点值得我们注意:试想下,在一对多的关系下我们首先加载的是一的这一方,然后是多的那一方,所以代码可以是:
上面的代码我们是直接保存Classes对象的,直接运行的话会产生异常:org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.fendou.hibernate.Student。原因是Student在未保存之前是一个瞬时对象,无法被持久化。有两种解决办法第一:先保存Student再保存Classes(把注释去掉),第二:在刚刚的Classes.hbm.xml配置中保留cascade="all"。
第二点值得我们注意的地方是:假设我们的属性字段允许为空,即Student.hbm.xml修改成<property name="name" length="50" column="sname" not-null="true"/>再把Classes.hbm.xml的配置:<set name="students" cascade="all" inverse="true">
去掉cascade="all" inverse="true"同样会报异常。因为我们先加载的是Classes对象,Hibernate只知道有一个Student对象,但对于他的数据约束信息一无所知,加载Student对象的时候并不知道字段可以为空,这样就会违反约束条件。
对于一对多的关联映射,我们一般会修改成双向关联,既可以从多的一端加载也可以从一的一端加载,方便操作。这样的话只需要在多的一端修改配置文件Student.hbm.xml。增加如下配置:<many-to-one name="classes" column="cid"/>注意字段名cid应该和一端的那边一致。
再介绍下:多对多关联关系映射。利用学生与课程之间的关系来解释,一个学生可以选择多门课程,一门课程可以被多个学生选。由于多对多的映射一般也会采用双向关联,所以只介绍双向关联的配置。如果我们用SQL语句来写的话,只需要建立第三张表,然后加入一个联合主键就可以,同理在Hibernate中也一样。现在我们的Student类有private int id;private String name;private Set<Course> courses;三个字段。Course类也有三个字段private int id;private String name;private Set<Student> students;项目结构如图:
![](http://hi.csdn.net/attachment/201106/5/0_1307247710KyWP.gif)
Student.hbm.xml和Course.hbm.xml配置如下图:
介绍下配置:多对多的映射:产生第三张表用来联系前两张表,且有联合主键
<set name="courses" table="sc">
<key column="sid" />
<many-to-many column="cid" class="Course" />
</set>
table表示含有联合主键的第三张表,key表示外键,<many-to-many>中的column表表示另外的一个外键,
class表示另外的一张表。
运行生成的代码如下:
drop table if exists sc
drop table if exists t_course
drop table if exists t_student
create table sc (sid integer not null, cid integer not null, primary key (cid, sid))
create table t_course (cid integer not null auto_increment, cname varchar(50), primary key (cid))
create table t_student (sid integer not null auto_increment, sname varchar(50), primary key (sid))
alter table sc add index FKE50367B2147 (sid), add constraint FKE50367B2147 foreign key (sid) references t_student (sid)
alter table sc add index FKE50BCE53EDB (cid), add constraint FKE50BCE53EDB foreign key (cid) references t_course (cid)
(未完待续,下次介绍继承映射)
首先,介绍下一对多。有人会有疑问:一对多和多对一不是一样的吗?下面我们接着用学生和班级的例子继续来说明下。一对多表示:控制方在一的这一端,比如可以查找属于同一个班级下的所有的学生。这个该怎么实现,试想下你要查找班级下的学生你的Classes类下面就必须要有Student类对象的这个属性字段。private Set<Student> students;利用这个属性来加载属于当前班级下的所有的学生。其他的属性字段同一对多的一样。项目结构图如下:
![](http://hi.csdn.net/attachment/201106/5/0_1307245060m6mg.gif)
当前使用的是一对多的映射,配置一般在一的一端。配置如下:
<hibernate-mapping package="com.fendou.hibernate"> <class name="Classes" table="t_classes"> <id name="id" column="cid"> <generator class="native"></generator> </id> <property name="name" length="50" column="cname"/> <set name="students" cascade="all" inverse="true"> <key column="cid"/> <one-to-many class="Student" /> </set> </class> </hibernate-mapping>
注意下当前我们使用的不再是<property>而是<set>标签。set标签中name和property的name一样表示利用Classes这个类的students属性来生成一个字段,该字段名字由<key>来指定也就是cid,并且该字段为Student的外键(由<one-to-many>来指定)。
运行下,同样的会产生如下的代码:
drop table if exists t_classes
drop table if exists t_student
create table t_classes (cid integer not null auto_increment, cname varchar(50), primary key (cid))
create table t_student (sid integer not null auto_increment, sname varchar(50), cid integer, primary key (sid))
alter table t_student add index FK4B907570D95D9B22 (cid), add constraint FK4B907570D95D9B22 foreign key (cid) references t_classes (cid)
配置的这个地方有两点值得我们注意:试想下,在一对多的关系下我们首先加载的是一的这一方,然后是多的那一方,所以代码可以是:
public void testAdd(){ Session session = null; Transaction tr = null; try { session = HibernateUtils.getSession(); //开启事务 tr = session.beginTransaction(); //实例化对象 Student s1 = new Student(); s1.setName("wyb"); //session.save(s1); Student s2 = new Student(); s2.setName("wym"); //session.save(s2); Set<Student> set = new HashSet<Student>(); set.add(s2); set.add(s1); Classes c = new Classes(); c.setName("FJSE35"); c.setStudents(set); session.save(c); tr.commit(); } catch (Exception e) { e.printStackTrace(); tr.rollback(); }finally{ HibernateUtils.closeSession(session); } }
上面的代码我们是直接保存Classes对象的,直接运行的话会产生异常:org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.fendou.hibernate.Student。原因是Student在未保存之前是一个瞬时对象,无法被持久化。有两种解决办法第一:先保存Student再保存Classes(把注释去掉),第二:在刚刚的Classes.hbm.xml配置中保留cascade="all"。
第二点值得我们注意的地方是:假设我们的属性字段允许为空,即Student.hbm.xml修改成<property name="name" length="50" column="sname" not-null="true"/>再把Classes.hbm.xml的配置:<set name="students" cascade="all" inverse="true">
去掉cascade="all" inverse="true"同样会报异常。因为我们先加载的是Classes对象,Hibernate只知道有一个Student对象,但对于他的数据约束信息一无所知,加载Student对象的时候并不知道字段可以为空,这样就会违反约束条件。
对于一对多的关联映射,我们一般会修改成双向关联,既可以从多的一端加载也可以从一的一端加载,方便操作。这样的话只需要在多的一端修改配置文件Student.hbm.xml。增加如下配置:<many-to-one name="classes" column="cid"/>注意字段名cid应该和一端的那边一致。
再介绍下:多对多关联关系映射。利用学生与课程之间的关系来解释,一个学生可以选择多门课程,一门课程可以被多个学生选。由于多对多的映射一般也会采用双向关联,所以只介绍双向关联的配置。如果我们用SQL语句来写的话,只需要建立第三张表,然后加入一个联合主键就可以,同理在Hibernate中也一样。现在我们的Student类有private int id;private String name;private Set<Course> courses;三个字段。Course类也有三个字段private int id;private String name;private Set<Student> students;项目结构如图:
![](http://hi.csdn.net/attachment/201106/5/0_1307247710KyWP.gif)
Student.hbm.xml和Course.hbm.xml配置如下图:
学生的配置: <hibernate-mapping package="com.fendou.hibernate"> <class name="Student" table="t_student"> <id name="id" column="sid"> <generator class="native"></generator> </id> <property name="name" length="50" column="sname"/> <set name="courses" table="sc" cascade="all"> <key column="sid" /> <many-to-many column="cid" class="Course" /> </set> </class> </hibernate-mapping> 课程的配置: <hibernate-mapping package="com.fendou.hibernate"> <class name="Course" table="t_course"> <id name="id" column="cid"> <generator class="native"></generator> </id> <property name="name" length="50" column="cname"/> <set name="students" table="sc" cascade="all"> <key column="cid"/> <many-to-many class="Student" column="sid" /> </set> </class> </hibernate-mapping>
介绍下配置:多对多的映射:产生第三张表用来联系前两张表,且有联合主键
<set name="courses" table="sc">
<key column="sid" />
<many-to-many column="cid" class="Course" />
</set>
table表示含有联合主键的第三张表,key表示外键,<many-to-many>中的column表表示另外的一个外键,
class表示另外的一张表。
运行生成的代码如下:
drop table if exists sc
drop table if exists t_course
drop table if exists t_student
create table sc (sid integer not null, cid integer not null, primary key (cid, sid))
create table t_course (cid integer not null auto_increment, cname varchar(50), primary key (cid))
create table t_student (sid integer not null auto_increment, sname varchar(50), primary key (sid))
alter table sc add index FKE50367B2147 (sid), add constraint FKE50367B2147 foreign key (sid) references t_student (sid)
alter table sc add index FKE50BCE53EDB (cid), add constraint FKE50BCE53EDB foreign key (cid) references t_course (cid)
(未完待续,下次介绍继承映射)
相关文章推荐
- 常用的Hibernate的映射与数据库表的关系(二)
- 常用的Hibernate的映射与数据库表的关系
- 常用的Hibernate的映射与数据库表的关系
- 【转】Hibernate之 对象/关系数据库映射基础(Basic O/R Mapping)
- Hibernate创建对象-关系映射文件和数据库
- Hibernate继承关系映射(了解),实现反向生成数据库表的过程
- 【Java】Hibernate(四)对象/关系数据库映射基础
- Hibernate映射数据库关系
- Hibernate 继承关系映射——共享一个数据库表
- hibernate3.6finald的Annotation实现实体类与数据库表的映射关系(不再需要hibernate-annotations.jar hibernate-commons-annota)
- hibernate---->对象/关系数据库映射基础
- Hibernate3.6中用Annotation来实现实体类与数据库表的映射关系
- 5 -- Hibernate的基本用法 --1 1 对象/关系数据库映射(ORM)
- Hibernate之 对象/关系数据库映射基础(Basic O/R Mapping)
- ORM和Hibernate---5.1.1: 对象/关系数据库映射(ORM)
- Hibernate之 对象/关系数据库映射基础(Basic O/R Mapping)
- hibernate---->对象/关系数据库映射基础
- hibernate配置文档常用配置、hbm配置文件(对象-关系映射)的基本配置
- Hibernate继承映射(反向映射到数据库) SchemaExport ,存在继承关系,从pojo文件映射出数据库文件
- Hibernate基于注解方式配置来实现实体和数据库之间存在某种映射关系