Hibernate 5.3 (四)

Hibernate 关联映射

客观世界中的对象很少有孤立存在的,这种实例对象之间的互相访问就是关联关系。

单向关系:只需单向访问关联端。例如,只能通过老师访问学生,或者只能通过学生访问老师。
双向关系:关联的两端可以互相访问。例如,老师和学生之间可以互相访问。

关联映射的类别

单向关联:

  • 单向1- 1
  • 单向1-N
  • 单向N-1
  • 单向N-N

双向关联:

  • 双向1-1
  • 双向1-N
  • 双向N-N

注意:双向关系里没有N- 1,因为双向关系1 -N和N- 1是完全相同的

单向 N-1 关联

访问顺序就是应该是从N方去访问1方。

N-1的关系在配置的时候,使用many-to-one元素,必须拥有name属性。

可选属性如下:

  • column:该属性指定进行关联的外键列的列名, 该列名默认与该属性同名。
  • class:该属性指定关联实体(持久化类)的全限定类名,默认是通过反射得到该属性所属类的类名。
  • cascade:该属性指定哪些持久化操作会从主表记录级联到子表记录。
  • fetch:该属性指定Hibernate的抓取策略,该属性值只能是join (使用外连接抓取)和select(使用选择抓取)两个值的其中之一。

比如现在有一个学生和班级的关联关系,你要通过某个学生查找班级的关系,下图是对应两个抓取策略的:

在这里插入图片描述

  • update, insert: 指定对应的字段是否包含在用于Hibernate生成的update或insert语句中,两个属性的默认值都是true。
    如果将二者指定为false,则表明这是一个纯粹的外源关联,它的值是通过映射同一个(或多个)字段的其他属性得到的,或由触发器或其他程序来负责生成。(我们正常理解,就是如果设置update、insert 这个属性是不可以插入和更新)
  • property-ref:指定关联类的一个属性,这个属性将会和本类的外键相对应(当外键参照唯一键时需指定该属性)。如果没有指定,直接使用对方关联类的主键。
  • unique:指定Hibernate通过DDL为外键列添加唯一约束。 此外,也可以用做property-ref的目标属性。 这使关联同时具有一对一的效果。
  • not-null: 指定使用DDL为外键字段添加非空约束。
  • optimistic-lock:该属性指定其更新时是否需要获得乐观锁定,也就是其值决定引用关联实体的属性发生改变时版本值是否增长。
  • lazy:指定引用关联实体的延迟加载特性,该属性只能接受false、proxy、 no-proxy 三个值。该属性默认值是proxy。实际上,Hibernate 默认会启动单实例关联(即多对一、一对一)的代理,指定 no-proxy 即要求该属性应该在实例变量第一次被访问时采用延迟抓取,lazy="false"指定此关联实体总是被预先抓取。
  • not-found: 该属性指定当外键参照的主表记录不存在时如何处理。该属性只接受ignore 和exception两个值,默认是exception,即不存在时抛出异常;如果程序希望Hibernate忽略这个异常,则可指定该属性值为ignore。
  • formula: 指定一一个SQL表达式,该外键值将根据该SQL表达式来计算。
使用例子(基于外键)

关联关系:多个人对应一个地址。

public class Person {
	private Integer id;
	private Integer age;
	private Address address;// 这里的属性不是一个组件属性,而是一个持久化类,这个是和之前不同
      //省略set、get方法,需自己补充

}

	 private Integer addressid;
         private String addressdetail;
         //省略set、get方法、自行补充
	
<class name="Person" table="PERSON" dynamic-insert="true" dynamic-update="false">
    <id name="id" type="integer" >
    <generator class="identity"></generator>
    </id>
    <property name="age" type="integer"></property>
    <!-- 这里的N-1 是持久类之间的映射关系 ,N对应的是从表,1 对应的是主表-->
    <!-- column 该属性的列名-->
      <!--cascade 这里的级联,对应到数据库中是级联更新和级联删除,级联更新是在更新的时候,优先更新主表,在更新从表,级联删除是在删除的时候,先删除从表,在删除主表 -->
    <many-to-one name="address" cascade="all" class="Address" column="address_id"></many-to-one>
    <!-- 在这里address 对应的属性应该映射成外键列,这里实际还要指定该外键列和主表哪一列关联property_ref指定,默认是和主表的主键关联 -->
</class>
<class name="Address" table="ADDRESS">
    <id name="addressid" column="address_id">
    <generator class="identity" ></generator>
    </id>
    <property name="addressdetail" />
</class>
 		   Person p = new Person();
		   p.setAge(20);
		   com.example.test.bean.Address a = new com.example.test.bean.Address();
		   a.setAddressdetail("大中路");
		   p.setAddress(a);
		   ss.save(p);//在前面的配置文件中,我已经说过N对应的是从表,1对应的是主表,我们这里认为
		   //一个1个地址,对应多个人,person是从表,你在插入从表的时候需要依照主表的相关联的键插入,可以
		   //在这看address 主表,还没有持久化,只是一个瞬态,所以抛出异常TransientObjectException。解决的办法就是在从表的映射文件
		   //中添加cascade="all",这时会先执行插入主表,然后插入从表,就不会有问题的。

注意:从表的插入更新都是相对于主表的,参看不了主表,你搞个捶捶。(删除的时候,就要反着来,先删除从表,咋在删主表)

上面这个例子在处理单向N-1的关系的时候,在N方加入一个外键,即可实现关联,但是有时也会在数据库新建一个表来维护这种关系,看下面的例子。

使用例子(基于关系维护表)

关联关系:多个人对应一个地址。

修改Person.hbm.xml

<join table="person_address"><!-- table 用于指定关联表 -->
     <key column="id" ></key><!-- 映射表参考主表的主键作为外键列,也是该表的主键列 -->
     <many-to-one name="address" cascade="all" class="Address" fetch="join"   column="address_id"></many-to-one>
 </join>

这时生成的关联表,两个字段都是以外键列存在的。

使用<join…>元素映射连接表时还需要外键关联, 应在配置文件中增加<ke…/>子元素来映射外键,并为join元素增加<many-to-on…/>子元素,用于映射N- 1的关联实体。该<many-to-on…/> 子元素的用法与不使用连接表的<many-to-on…/>子元素的用法完全相同。

单向的1-1

访问的顺序:你在某个持久类A中定义另外一个持久化类B的实体,顺序就是A-B,A是从表,B是主表。

单向的1-

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值