Hibernate多对多关系配置及延迟加载随笔

1、多对多关系如何配置

  有三张表 role、permission,分别是角色与权限表,二者是多对多关系,对应关系的中间表为p_role_permission,中间表中r_sysId对应role表中的主键sysId、中间表中p_sysId列对应permission表中的主键sysId(说白了就是中间表中两列是外键列分别指向role和permission表)。下面代码是role表对应的注解配置实体类


@Entity
@Table(name="role",catalog="byky")
     pubic class Role{
        	......
        	@ManyToMany(fetch=FetchType.LAZY)
        	@JoinTable(name="p_role_permission",joinColumns=     {@JoinColumn(name="r_sysId",referencedColumnName = "sysId")},inverseJoinColumns={@JoinColumn(name="p_sysId",referencedColumnName = "sysId")})
        	  public Set<Permission> getPermissions() {
        			return permissions;
        	  }
        	......
        } 
  • @ManyToMany注解中fetch值可选两种配置fetch=FetchType.LAZY表示延迟加载,使用代理技术,当role对象加载时role对象的permissions属性,暂不加载,当调用role的getPermissions() 是hibernate采取去查询数据库去加载数据。有一点需要特别强调的,延迟加载是需要与hibernate的session在打开状态的,当前role对象关联的session关闭了,在调用role对象的permissions属性时会报错com.sun.jdi.InvocationException错误。所以千万注意不要把对于延迟加载的属性值的获取放到session关闭之后,常见的是Contreller中去调用,除非使用声明式的事物,延迟getCurrentSession方法的关闭。
  • @ManyToMany注解中fetch值配置fetch=FetchType.EAGER 时表示立即加载,是不会session关闭读不到数据现象,但会造成数据查询冗余,没有用的属性一次性都读出来,对数据库造成压力。
  • @JoinTable 中name="p_role_permission"配置的是中间表的名称,joinColumns= {@JoinColumn(name=“r_sysId”,referencedColumnName = “sysId”)}中@JoinColumn(name="r_sysId"配置的是当前类对应表在中间表中的外键字段,referencedColumnName = "sysId"配置的是当前类中对应中间表外键的主键字段;
    inverseJoinColumns={@JoinColumn(name=“p_sysId”,referencedColumnName = “sysId”)}是指与当前类多对多对应的另一个表permission,第一个@JoinColumn(name="p_sysId"也是permission表在中间表中对应的外键字段,referencedColumnName = “sysId”)只permission中与中间表外键p_sysId字段对应的主键字段sysId。
  • cascade级联操作比较重要,单独放一个标题讲解。

2、cascade级联操作

hibernate的cascade操作是针对对象与对象,这一点从cascade的可配置项上就能看出来,考虑的时候不要和数据库中的级联操作进行混淆。
两种cascade的配置方式:

在@OneToOne、@OneToMany、@ManyToOne、@ManyToMany的注解上配置,使用的是javax.persistence.CascadeType也就是JPA的配置

 @ManyToMany(fetch=FetchType.LAZY,casecade={CasecadeType.DETACH,CascadeType.MERGE})

casecade的内容是个CasecadeType类型的数组。可以配置多个内容,如果只有一个配置项则可直接写成 casecade=CasecadeType.DETACH,在代码中的形式是这样的

@ManyToMany(fetch=FetchType.LAZY,casecade=CascadeType.MERGE)

另一种配置方式是使用org.hibernate.annotations.CascadeType,也就是hibernate的注解配置形式如下

@ManyToMany(fetch=FetchType.LAZY)
@Cascade(value={ org.hibernate.annotations.CascadeType.DETACH})
@JoinTable(name="p_role_permission",joinColumns={@JoinColumn(name="r_sysId",referencedColumnName = "sysId")},inverseJoinColumns={@JoinColumn(name="p_sysId",referencedColumnName = "sysId")})
public Set<PPermission> getPermissions() {
	return permissions;
}

可以看出来使用了@Casecade注解,其中value值是一个org.hibernate.annotations.CascadeType类型数组,可以配置多个值也可以设置一个值。
Casecade作用:是否级联被注解字段里面的对象。使用JPA设置时可选值:javax.persistence.CascadeType.PERSIST, MERGE, REMOVE, REFRESH, DETACH, ALL。可选其中的一个或多个,选一个时,花括号可用可不用

可选值说明
PERSIST级联session的persist操作。假设Student类和teachers字段的@ManyToMany注解上配置有cascade = {CascadeType.PERSIST},那么,当stu1对象set了一个teachers集合(这个集合里面的对象都是瞬态的),持久化这个stu1d对象时,这个集合里面的所有瞬态对象都会被级联持久化到数据库。
MERGE级联merge操作。道理同上
REFRESH级联refresh操作。道理同上
REMOVE级联remove操作。道理同上
DETACH级联evict操作。道理同上
ALL级联以上所有操作
以上前五种选择值分别与session中的方法进行对应关联,只有对应的方法才能触发

如果使用使用Hibernate自身注解的CascadeType.可选值如下:

可选值说明
DELETE级联session中的delete方法
DELETE_ORPHAN已过时不建议使用
DETACH相当于JPA的CascadeType.DETACH
EVICT已过时,请使用上一项DETACH
MERGE相当于CascadeType.MERGE
PERSIST相当于CascadeType.PERSIST
REFRESH相当于 CascadeType.REFRESH
REMOVE相当于CascadeType.REMOVE.
REPLICATE级联session中的REPLICATE方法
SAVE_UPDATE级联 session.save() or session.update() or session.saveOrUpdate()三个方法
ALL级联以上所有操作

注意,如果级联操作使用不当反倒影响性能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值