Hibernate 关系映射整理

一、概念:


关系:名词,事物之间相互作用、相互联系的状态。
关联:名词:表示对象(数据库表)之间的关系;动词:将对象(数据库表)之间通过某种方式联系起来。
映射:将一种形式转化为另一种形式,包括关系。
级联:动词,有关系的双方中操作一方,另一方也将采取一些动作。
 
值类型:对象不具备数据库同一性,属于一个实体实例其持久化状态被嵌入到所拥有的实体的表行中,没有标识符。
实体类型:具有数据库标识符。
 
二、数据库:


1、关系
2.1.1、一对一、一对多、多对多
2.1.2、如何表示? 外键+索引


2、级联:
2.2.1、级联增加

2.2.2、级联删除

2.2.3、级联修改

2.2.4、级联查询


三、面向对象语言中(Java中):


1、关系
3.1.1、一对一、一对多、多对多
3.1.2、如何表示? 实例变量(对象+集合)


2、级联:
3.2.1、级联删除
3.2.2、级联更新
3.2.3、级联保存


四、如何把数据库关系表示为面向对象中的关系:


1、关联:将数据库表之间的关系转化为对象之间的关系;在Hibernate中总指实体之间的关系。

2、映射:完成java对象到数据库表的双向转换。

3、级联(可选):将数据库中的级联转化为对象中的级联(两者(对象和数据库表)没关系)。

4、Hibernate的表和对象的映射:


1)、实体类型映射:

      4.1.1、主键之间的映射
      4.1.2、类属性与表字段的映射(基本映射)
      4.1.3、组件映射
      4.1.4、集合映射
      4.1.5、继承映射


2)、实体关联关系映射:

     1、单向一对一关联映射(one-to-one)
     2、单向多对一关联映射(many-to-one)
     3、单向一对多关联映射(one-to-many)
     4、单向多对多映射(many-to-many)
     5、双向一对一关联映射
     6、双向一对多关联映射
     7、双向多对多关联映射


Hibernate中的实体关系分为四种,基本上与我们在数据库建模中了解到的实体关系是一样的,即一对一关系、一对多关系、多对一关系、多对多关系。


一、一对一关系、多对一关系

  一对一、多对一关系在代码上的体现是在JavaBean中包含一个实体类属性。比如,夫妻关系是一对一的关系,那么丈夫的属性中就应该有一个属性是妻子,妻子的属性中也应该有一个属性是丈夫。同样,多对一的关系中,在代码上的体现也是在Java中包含一个实体类属性。比如,孩子与妈妈的关系就是多对一的关系,每一个孩子都应该有一个属性是妈妈。我们发现,无论是一对一,还是多对一,它们在代码是都是一样的,就是属性中包含一个实体类属性。而事实上,一对一关系是多对一关系的一种特例而已。所以,在映射时,由外键实现的一对一关系或多对一关系时,无论是哪一种,外键所在一方关系属性都是通过many-to-one映射的,而不是用one-to-one。

二、一对多关系、多对多关系

  这两种关系也有些共性,就是它们在代码上的体现都是在JavaBean中包含一个集合属性。比如在上面说的妈妈与孩子的关系,妈妈应该包含一个集体属性,在这个集合中包含了她所有的小孩。这种一对多关系使用one-to-many来映射,在数据库中的体现是在一的一方是不含有外键的。而多对多的关系虽然也是在属性中包含一个集合属性,但在映射时使用的却是many-to-many。这主要是因为多对多关系需要一个关系表,必须告诉Hibernate这个关系表是谁。


3)、单向与多向


双向单向是面向对象的说法 意思就是你更新一个表另外一个表里面关联的数据跟着改变。


(1)、双向就是这两个表无论哪一个更新另外一个表都更新 。
(2)、单向就是只有一个主表更新从表才更新 从表更新主表不管。


单向就是只能从一方找到另一方,通常是从主控类找到拥有外键的类(表)。比如一个母亲可以有多个孩子,并且孩子有母亲的主键作为外键。母亲与孩子的关系就是一对多的关系。如果想对母亲信息的操作同时也反应在其孩子信息上那么可以在母亲类配置文件的集合属性上配置cascade="all",表示对关联实体进行级联更新配置。

双向就是双方都能各自的引用,能够通过A表找到B表,通过B表找到A表。


当使用单向关联时,由父类管理关联关系,子类无法管理;而这时,父亲知道自己的儿子,但是,儿子对象不知道父亲是谁。
单向关联时,只需指定<one-to-many> 。


当使用双向关联时,关联关系的管理可以通过inverse指定,这时,儿子能清楚的知道自己的父亲是谁。 
双向关联时,还需要指定<many-to-one>。


示例:


多对一:

就是A表中的一个字段是B表的主键。多个A表中的数据可以对应一个B表中的数据,同理,一个B表中的数据可以同时对应多个A表中的数据。

单向关联与双向关联对数据表的要求其实是一致的。满足对应的关联要求即可,也就是A表中的一个字段是B表中的主键。

单向关联与双向关联的需求是不一样的。单向关联,只需要可以通过主表找到控表即可。这个很简单,通过简单的sql语句,select B from A where A.B=?即可。需要的配置也很简单,在A表的持久化类的映射文件中加入:

<class ......>
   <id....>
   ......
   <many-to-one name="B" class="com.bean.B">
       <column name="B"/>  <!--这个B是A表中B表的主键对应的外键名-->
   </many-to-one>
</class>

双向关联的需求是:能够通过A表找到B表,通过B表找到A表。怎么实现呢?

我们可以知道,单存的B表数据找到的是一批A表的数据,也就是A表数据对象的集合,当然,改变的不是数据库中的表,而是持久化类。B表的持久化类中加入一个A表的Set集合,将查询到的与B有关的数据放入该集合中,之后就可以通过其他的条件得到我们想要的对应A的信息了。

做法:

1、B持久化类中饭加入A的set集合以及对应get set方法
2、在B表的映射文件中加入Set信息以及一对多信息:


<set name="As" inverse="true">
  <key column="B.id"/>
  <on-to-many class="com.bean.A"/>
</set>

之后就可以通过一系列的操作实现我们的需求了!


我们来对比一下单向和双向

单向/双向 User实体类中是否有List< Order> orders Order实体类中是否有User user
单向多对一
单向一对多
双向一对多(双向多对一)




5、映射关系的方向性问题


一个关系也一定有两个实体。这就存在了另外一个问题,当一个实体发生变化时,关系是不是也一定要跟着变化?

这种问题很难说清,因为它跟具体的应用关联。有时,我们只要更新实体,而不想更新关系;

而有时我们又想更新关系而不更新实体;还有些情况下,我们是实体和关系同时都要更新。

在默认情况下,Hibernate对于实体和关系是同时更新的,即使你根本没有更改过关系。这对于性能的影响比较大。

我们可以给关系设置一个inverse属性,告诉它在任何变化下,都不要更新关系。当然还有其它的办法,

读者可以参考其文档。总之,这是一个非常复杂的问题,要视你的应用而定。


一对多单向映射:多对一的映射关系是在多的一端进行维护的,一对多关系映射则由一端来维护这种关系。


双向一对多关系:一是关系维护端(owner side),多是关系被维护端(inverse side)。

在关系被维护端需要通过@JoinColumn建立外键列指向关系维护端的主键列。



五、关系映射关系目录


Hibernate关联关系映射目录
│ 
├─单向关联
│  ├─  一对一外键单向关联
│  ├─  一对一主键单向关联
│  ├─  一对一连接表单向关联
│  ├─  一对多外键单向关联
│  ├─  一对多连接表单向关联
│  ├─  多对一外键单向关联
│  ├─  多对一连接表单向关联
│  └─  多对多单向关联
└─双向关联
    ├─  一对一外键双向关联
    ├─  一对一主键双向关联
    ├─  一对一连接表双向关联
    ├─  一对多外键双向关联
    ├─  一对多连接表双向关联
    └─  多对多双向关联


六、示例


这里使用两种方式来讲解:


1)XML

2)注解


(一)XML


hibernate在实现ORM功能的时候主要用到的文件有:映射类(*.Java)、映射文件(*.hbm.xml)和数据库配置文件(*.properties/*.cfg.xml),它们各自的作用如下:

        映射类*.java:它是描述数据库表的结构,表中的字段在类中被描述成属性,将来就可以实现把表中的记录映射成为该类的对象了。

        映射文件(*.hbm.xml:它是指定数据库表和映射类之间的关系,包括映射类和数据库表的对应关系、表字段和类属性类型的对应关系以及表字段和类属性名称的对应关系等。

        数据库配置文件(*.properties/*.cfg.xml:它是指定与数据库连接时需要的连接信息,比如连接哪种数据库、登录数据库的用户名、登录密码以及连接字符串等。当然还可以把映射类的地址映射信息放在这里。


(二)、注解


在实体类中添加JPA的标准注解来进行对象关系映射.注解可以添加在属性上,也可以添加在getXxx()方法之上。

@Entity    --注释声明该类为持久类。将一个Javabean类声明为一个实体的数据库表映射类,最好实现序列化.此时,默认情况下,所有的类属性都为映射到数据表的持久性字段.若在类中,添加另外属性,而非映射来数据库的, 要用下面的Transient来注解。
@Table(name="promotion_info")      --持久性映射的表(表名="promotion_info).@Table是类一级的注解,定义在@Entity下,为实体bean映射表,目录和schema的名字,默认为实体bean的类名,不带包名.
@Id--注释可以表明哪种属性是该类中的独特标识符(即相当于数据表的主键)。
@GeneratedValue   --定义自动增长的主键的生成策略.
@Transient             --将忽略这些字段和属性,不用持久化到数据库.适用于,在当前的持久类中,某些属性不是用于映射到数据表,而是用于其它的业务逻辑需要,这时,须将这些属性进行transient的注解.否则系统会因映射不到数据表相应字段而出错.
@Temporal(TemporalType.TIMESTAMP)--声明时间格式
@Enumerated         --声明枚举
@Version                --声明添加对乐观锁定的支持
@OneToOne            --可以建立实体bean之间的一对一的关联
@OneToMany          --可以建立实体bean之间的一对多的关联
@ManyToOne          --可以建立实体bean之间的多对一的关联
@ManyToMany        --可以建立实体bean之间的多对多的关联
@Formula               --一个SQL表达式,这种属性是只读的,不在数据库生成属性(可以使用sum、average、max等)
@OrderBy               --Many端某个字段排序(List)



1、hibernate单向一对一关联映射(one-to-one)




2、hibernate单向多对一关联映射(many-to-one)




3、hibernate单向一对多关联映射(one-to-many)




4、hibernate单向多对多映射(many-to-many)



5、hibernate双向一对一主键关联映射




6、hibernate双向一对多关联映射



7、hibernate双向多对多关联映射



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值