hibernate中的关系映射

Hibernate中的关系可以分为:单向关系和双向关系。顾名思义说的是从一方是否可以访问另一方,对应到数据库中也就是根据一方的值是否也可以检索出另一方的值了。

单向关联可以分为:

<!--[if !supportLists]-->l         <!--[endif]-->单向1-1

<!--[if !supportLists]-->l         <!--[endif]-->单向1-N

<!--[if !supportLists]-->l         <!--[endif]-->单向N-1

<!--[if !supportLists]-->l         <!--[endif]-->单向N-N

双向关联可以分为:

<!--[if !supportLists]-->l         <!--[endif]-->双向1-1

<!--[if !supportLists]-->l         <!--[endif]-->双向1-N

<!--[if !supportLists]-->l         <!--[endif]-->双向N-N

单向1-N

一个老师对应多个学生,那么需要在老师的模型中定义一个set或者list集合来存储多个学生。

Xml配置:

<class name="Student" table="student">

       <id name="stu_id" type="string">

              <generator class="uuid"/>

       </id>

       <property name="stu_name" type="string"/>

</class>

 

<class name="Teacher" table="teacher">

       <id name="tea_id" type="string">

              <generator class="uuid"/>

       </id>

       <property name="tea_name" type="string"/>

       <!—设置级联关系为全级联,即当这一方更新数据的时候,会影响另一方的数据 -->

       <set name="students" cascade=”all”>

              <!—key就是在student表中指定的外键 -->

              <key column="dong"/>

              <one-to-many class="Student"/>

       </set>

</class>

生成的建表语句:

alter table student drop foreign key FK8FFE823B3010B624

drop table if exists student

drop table if exists teacher

create table student (stu_id varchar(255) not null, stu_name varchar(255), dong varchar(255), primary key (stu_id))

create table teacher (tea_id varchar(255) not null, tea_name varchar(255), primary key (tea_id))

alter table student add index FK8FFE823B3010B624 (dong), add constraint FK8FFE823B3010B624 foreign key (dong) references teacher (tea_id)

插入测试:

Hibernate: insert into teacher (tea_name, tea_id) values (?, ?)

Hibernate: insert into student (stu_name, stu_id) values (?, ?)

Hibernate: insert into student (stu_name, stu_id) values (?, ?)

Hibernate: insert into student (stu_name, stu_id) values (?, ?)

//当执行完插入的时候,要更新外键值

Hibernate: update student set dong=? where stu_id=?

Hibernate: update student set dong=? where stu_id=?

Hibernate: update student set dong=? where stu_id=?

 

查询测试:

//查询teacher表中的指定元素

Hibernate: select teacher0_.tea_id as tea1_1_0_, teacher0_.tea_name as tea2_1_0_ from teacher teacher0_ where teacher0_.tea_id=?

//输出teacheridname

402881e437a109780137a10979ac0001:dong

//查询student表中的内容

Hibernate: select students0_.dong as dong1_, students0_.stu_id as stu1_1_, students0_.stu_id as stu1_0_0_, students0_.stu_name as stu2_0_0_ from student students0_ where students0_.dong=?

//输出学生的数目

3

 

删除测试:

//查询指定的记录

Hibernate: select teacher0_.tea_id as tea1_1_0_, teacher0_.tea_name as tea2_1_0_ from teacher teacher0_ where teacher0_.tea_id=?

//查询该记录所级联的相关记录

Hibernate: select students0_.dong as dong1_, students0_.stu_id as stu1_1_, students0_.stu_id as stu1_0_0_, students0_.stu_name as stu2_0_0_ from student students0_ where students0_.dong=?

//更改其级联关系,使得要删除的指定记录变得可以删除

Hibernate: update student set dong=null where dong=?

//删除指定记录及其级联记录

Hibernate: delete from student where stu_id=?

Hibernate: delete from student where stu_id=?

Hibernate: delete from student where stu_id=?

Hibernate: delete from teacher where tea_id=?

单向N-1

Xml配置:

<class name="Student" table="student">

       <id name="stu_id" type="string">

              <generator class="uuid"/>

       </id>

      

       <property name="stu_name" type="string"/>

      

       <many-to-one name="teacher" class="Teacher" column="teacher_id" cascade="all"/>

</class>

 

<class name="Teacher" table="teacher">

       <id name="tea_id" type="string">

              <generator class="uuid"/>

       </id>

       <property name="tea_name" type="string"/>

</class>

建表语句:

alter table student drop foreign key FK8FFE823BE8C01538

drop table if exists student

drop table if exists teacher

create table student (stu_id varchar(255) not null, stu_name varchar(255), teacher_id varchar(255), primary key (stu_id))

create table teacher (tea_id varchar(255) not null, tea_name varchar(255), primary key (tea_id))

alter table student add index FK8FFE823BE8C01538 (teacher_id), add constraint FK8FFE823BE8C01538 foreign key (teacher_id) references teacher (tea_id)

插入测试:

源代码:

session = sessionFactory.openSession();

tx = session.beginTransaction();

 

Teacher t = new Teacher();

t.setTea_name("hello");

 

Student st = new Student();

st.setStu_name("dong");

st.setTeacher(t);

 

Student st1 = new Student();

st1.setStu_name("jing");

st1.setTeacher(t);

 

session.save(st1);

session.save(st);

tx.commit();

//容易发现hibernate对此作了优化

Hibernate: insert into teacher (tea_name, tea_id) values (?, ?)

Hibernate: insert into student (stu_name, teacher_id, stu_id) values (?, ?, ?)

Hibernate: insert into student (stu_name, teacher_id, stu_id) values (?, ?, ?)

 

删除测试:

由于在多的一方设置的级联决定方,那么当删除一个student的时候,也就会删除对应的teacher,但是还有其他的student与该teacher对应,那么就会出现异常操作,所以很多时候是一的那一方设置cascade属性。

单向1-1

它有两种方法:1、将其看成1-N的特例,即在N的一段设置为unique=”true”即可;2、将两个表的主键设置为一样的,即一个表自动生成主键,另一个表的主键链接到该表的主键;3、外键关联。

第一种方法的配置和1-N的配置基本一样,只需要在<many-to-one>的标签中增加unique=”ture”这个属性即可。

下面来看第二种方法的配置:

<class name="Student" table="student">

       <id name="stu_id" type="string">

              <!-- 引用外键 -->

              <generator class="uuid">

                     <param name="property">teacher</param>

              </generator>

       </id>

       <property name="stu_name" type="string"/>

       <!--由于该表的主键是靠其他表的主键生成,则此处必须增加constrained="true"属性 -->

       <one-to-one name="teacher" constrained="true"/>            

</class>

<class name="Teacher" table="teacher">

       <id name="tea_id" type="string">

              <generator class="uuid"/>

       </id>

       <property name="tea_name" type="string"/>

</class>

生成的SQL语句:

alter table student drop foreign key FK8FFE823BFAB829A6

drop table if exists student

drop table if exists teacher

create table student (stu_id varchar(255) not null, stu_name varchar(255), primary key (stu_id))

create table teacher (tea_id varchar(255) not null, tea_name varchar(255), primary key (tea_id))

alter table student add index FK8FFE823BFAB829A6 (stu_id), add constraint FK8FFE823BFAB829A6 foreign key (stu_id) references teacher (tea_id)

------------------------------------------------------------------------------------------------------------------

插入测试:

Hibernate: insert into teacher (tea_name, tea_id) values (?, ?)

Hibernate: insert into student (stu_name, stu_id) values (?, ?)

====================================================================

单向N-N

单向N-N的配置与单向1-N的配置极其相似,但是它默认情况下需要有一个中间表连接,下面看看实例吧:

Xml配置:

<class name="StudentInfo" table="student">

       <id name="stu_id" type="string">

       <generator class="uuid"/>

       </id>

      

       <property name="stu_name" type="string"/>

      

       <!-- 中间表的名字 -->

       <set name="courses" table="s_c">

              <!-- 表中与该模型关联的外键 -->

              <key column="stu_id"/>

              <!-- 表中与另一个模型关联的外键及其所在类 -->

              <many-to-many class="StudentCourse" column="course_id"/>

       </set>

</class>

 

<class name="StudentCourse" table="course">

       <id name="course_id" type="string">

              <generator class="uuid"/>

       </id>

       <property name="course_name" type="string"/>

</class>

下面是生成的SQL建表语句:

alter table s_c drop foreign key FK1BB975DF8944D

alter table s_c drop foreign key FK1BB979FCE8E33

drop table if exists course

drop table if exists s_c

drop table if exists student

create table course (course_id varchar(255) not null, course_name varchar(255), primary key (course_id))

create table s_c (stu_id varchar(255) not null, course_id varchar(255) not null, primary key (stu_id, course_id))

create table student (stu_id varchar(255) not null, stu_name varchar(255), primary key (stu_id))

alter table s_c add index FK1BB975DF8944D (stu_id), add constraint FK1BB975DF8944D foreign key (stu_id) references student (stu_id)

alter table s_c add index FK1BB979FCE8E33 (course_id), add constraint FK1BB979FCE8E33 foreign key (course_id) references course (course_id)

--------------------------

插入测试:

Hibernate: insert into student (stu_name, stu_id) values (?, ?)

Hibernate: insert into course (course_name, course_id) values (?, ?)

Hibernate: insert into course (course_name, course_id) values (?, ?)

Hibernate: insert into student (stu_name, stu_id) values (?, ?)

Hibernate: insert into course (course_name, course_id) values (?, ?)

Hibernate: insert into s_c (stu_id, course_id) values (?, ?)

Hibernate: insert into s_c (stu_id, course_id) values (?, ?)

Hibernate: insert into s_c (stu_id, course_id) values (?, ?)

Hibernate: insert into s_c (stu_id, course_id) values (?, ?)

--------------------------

删除测试:

不能设置为全级联,否则当删除某一方的数据时,会将与其级联的另一方的数据删除,会影响中间连接表中其他的数据。

当然,除了上面在表内直接连接,还可以通过新建一个连接表,将两个表进行连接,此时所需要用到的标签就是<join>join元素的table属性用于确定连接表的表名;使用key子元素来确定连接表外键,并且要为连接表增加一个many-to-one子元素,该子元素用于映射关联属性。

下面通过一个例子来描述一下其一般过程:

Xml配置文件:

<class name="Student" table="student">

       <id name="stu_id" type="string">

              <generator class="uuid"/>

       </id>

      

       <property name="stu_name" type="string"/>

       <join table="join_table">

              <key column="teacher_id"/>

              <many-to-one name="teacher" cascade="all"/>

       </join>

      

</class>

 

<class name="Teacher" table="teacher">

       <id name="tea_id" type="string">

              <generator class="uuid"/>

       </id>

       <property name="tea_name" type="string"/>

</class>

生成的SQL语句:

alter table join_table drop foreign key FK6F0A7479CE8CCB91

alter table join_table drop foreign key FK6F0A7479DA135E82

//多了一个连接表

drop table if exists join_table

drop table if exists student

drop table if exists teacher

//连接表中的内容也就是连接两个表的键值

create table join_table (teacher_id varchar(255) not null, teacher varchar(255), primary key (teacher_id))

//两个表无序另设外键

create table student (stu_id varchar(255) not null, stu_name varchar(255), primary key (stu_id))

create table teacher (tea_id varchar(255) not null, tea_name varchar(255), primary key (tea_id))

//将连接表与被连接的两个表进行关联

alter table join_table add index FK6F0A7479CE8CCB91 (teacher_id), add constraint FK6F0A7479CE8CCB91 foreign key (teacher_id) references student (stu_id)

alter table join_table add index FK6F0A7479DA135E82 (teacher), add constraint FK6F0A7479DA135E82 foreign key (teacher) references teacher (tea_id)

插入操作,此处插入的是两条记录:

Hibernate: insert into teacher (tea_name, tea_id) values (?, ?)

Hibernate: insert into student (stu_name, stu_id) values (?, ?)

Hibernate: insert into join_table (teacher, teacher_id) values (?, ?)

Hibernate: insert into student (stu_name, stu_id) values (?, ?)

Hibernate: insert into join_table (teacher, teacher_id) values (?, ?)

 

 

 

 

 

双向关联

其实所谓的双向关联,就是“站在自己的角度看关系”,例如:一个1-N的关系,如果我站在1的这一方,那么对于我而言,我和你就是1-N的关系;但是如果我站在N的这一方,那么对于我而言,我和你就是N-1的关系。那么其配置就和单向的一样了。

但是这样就会出现了一个问题,就是控制权的问题,也就是cascade要“听谁的话”的问题。还拿1-N的例子讲,我们可以在1的这一方生成多的这一方,也可以在N的这一方生成1的这一方,那么到底该如何的设置呢?

下面就简单看看这些问题。

 

双向1-N

Hibernate对于1-N的关联推荐使用双向关联,但不用1的这一端来控制关联关系,反而使用N的这一端来控制。例如:一个人可以对应多个地址,那么我们就可以用人控制地址。

双向1-1

<!--[if !supportLists]-->1、  <!--[endif]-->基于外键的双向1-1

基于外键的双向1-1关联,外键可以放在任意一边,在需要放外键的一段增加many-to-one元素。并且为many-to-one元素增加unique=”true”属性来表示1-1关联;并用name属性来指定关联属性的属性名。

另一端使用one-to-one元素,该元素使用name属性指定关联的属性名。为了让系统懂得不在为本表中增加一列,因此使用外键关联,用property-ref属性来引用关联类的自身属性。

<!--[if !supportLists]-->2、  <!--[endif]-->基于主键的双向1-1

两边都是one-to-one元素,需要在引用对方主键的那一端设置generatorclass属性为foreign,并且其子标签paramname属性值为property,内容为与其关联的属性;还要为one-to-one元素设置属性constrained=”true”

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wlzjdm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值