Hibernate Annotation关系映射有下面几种类型:
1) 一对一外键关联映射(单向)
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="userid",unique=true)
一对一外键关联,使用@OneToOne,并设置了级联操作。@JoinColum设置了外键的名称为userid(数据库字段名),如果不设置,则默认为另一类的属性名+ _id,外键的值是唯一的(unique)。
@OneToOne:一对一映射。它包含五个属性:
targetEntity:关联的目标类
Cascade:持久化时的级联操作,默认没有
fetch:获取对象的方式,默认EAGER
Optional:目标对象是否允许为null,默认允许
mappedBy:定义双向关联中的从属类。
2) 一对一外键关联映射(双向)
Class1里与上面一样,
Class2:
@OneToOne(mappedBy="class2",cascade=CascadeType.ALL)
一对一双向关联关系,使用@OneToOne
注意:需要加上mappedBy="class2",如果不加上的话,Class2也会生成一个外键(class1_id),mappedby="class2"需要指向与他关联对象的一个属性,说明双向关联关系中,有且仅有一端是作为主体(owner)端存在的,主体端负责维护联接列,对于不需要维护这种关系的从表则通过mappedBy属性进行声明,mappedBy的值指向主体的关联属性
规律:只有是双向关联关系,都加上mappedby
3)(嵌入式对象)组件映射
将另外一个类成为实体类的一部分进行映射;
注意:1.成为其他实体类一部门的类不要注解为@Entity 实体类!
2. 使用@Embedded 将其类注解即可;
3.组件属性名名为了保证不与实体类属性名冲突,可以使用如下注解:
3.1 使用如下形式:
1234567@AttributeOverrides
(
{
@AttributeOverride
(name=
"xx"
,column=
@Column
(name=
"xxx"
)),
@AttributeOverride
(name=
"xx2"
,column=
@Column
(name=
"xxx2"
)),
}
)
3.2 在嵌入式对象里,对其属性使用@column进行设置
4) 一对多关联映射(单向)
@OneToMany
@JoinColumn(name="orgid")
/**
* 一对多注解@OneToMany(单向)
* 如果只写@OneToMany的话,hibernate会建一张中间表来
* 维护他们之间的关系,
* 加上@JoinColumn(name="orgid"),则不会建中间表,他会在
* 多的一端加上外键orgid,来维护他们之间的关系
*/
5) 一对多关联映射(双向)
一端:
@OneToMany(mappedBy="org")
@JoinColumn(name="orgid")
/**
* 一对多双向,在一的一端中设置mappedBy
* 说明多的一端为主导
* 如果指定了外键字段名称,则多的一端也需要指定相同的字段名称
*/
多端:
@ManyToOne
@JoinColumn(name="orgid")
/**
* 一对多双向
* 需要指定外键与一的一端给的外键名称一致,@JoinColumn(name="orgid")
* 也可以不指定,如果在多的一端不指定,则一的一端也不能指定
* 否则为生成两个外键
*/
6) 多对一关联映射
在多的一端配置:
@ManyToOne(targetEntity=Organization.class)
@JoinColumn(name="orgid")
//多对一注解@ManyToOne
//targetEntity指定了关联对象
//@JoinColumn(name="orgid")指定生产的外键的字段名,默认是org_id
7) 多对多关联映射(单向)
@ManyToMany
/**
* 多对多映射:注解@ManyToMany(单向)
* 默认情况下,hibernate会自动的创建一张中间表,
* 来维护多对多关系
* 默认中间表的名称 :user_role中间表,字段的名称user_id role_id
* 如果想更换表名和字段名称,注解如下:
*/
@JoinTable(name="t_u_r",
joinColumns={@JoinColumn(name="u_id")},
inverseJoinColumns={@JoinColumn(name="r_id")}
)
8) 多对多关联映射(双向) User端
@ManyToMany
/**
* 多对多映射:注解@ManyToMany(单向)
* 默认情况下,hibernate会自动的创建一张中间表,
* 来维护多对多关系
* 默认中间表的名称 :user_role中间表,字段的名称user_id role_id
* 如果想更换表名和字段名称,注解如下:
*/
@JoinTable(name="t_u_r",
joinColumns={@JoinColumn(name="u_id")},
inverseJoinColumns={@JoinColumn(name="r_id")}
)
/**
* @JoinTable(name="t_u_r",
* 指定中间表的表名
* joinColumns={@JoinColumn(name="u_id")},
* 指定当前对象的外键
* inverseJoinColumns={@JoinColumn(name="r_id")}
* 指定关联对象的外键
*/
Role端
@ManyToMany(mappedBy="role")
/**
* 多对多,双向关联映射
*/
级联(cascade)属性
1、CascadeType.ALL(包括增、删、改、查,联动操作),其实查不算在内,查Fetch
2、CascadeType.MERGE(合并的join)--不重要
3、CascadeType.PERSIST(保存的时候在级联)
4、CascadeType.REFRESH(刷新说明:比如现在我查询出了数据,另外一个人在我查询数据之后,他对数据做了修改,这是才会级联上,hibernate会自动刷新我查询出来的数据)
5、CascadeType.REMOVE (只要在删除操作时才会级联)
6、我们一般都只设置CascadeType.ALL就OK了,
7、Cascade不是必须的,他的作用只是可以让我们快速的开发,我们也可以通过手动增、删、改、查
Fetch捉取策略
1、FetchType.EAGER(渴望的,希望马上得到)
a) 一对多关系,比如通过get()方法来get出一的一端,他之后会出一条SQL语句,不会自动去查询多的一端,如果设置FetchType.EAGER,会讲他的关联对象查询出来
b) 如果是load的话,他不会发出SQL语句,因为load支持延迟加载,只有真正获取数据时才会发SQL
2、FetchType.LAZY(懒加载)
a) 只有真正获取数据时才发出SQL语句
3、默认是:FetchType.LAZY(一对多)
4、默认是:FetchType.EAGER(多对一)
5、一般使用默认就可以了
Hibernate基于注解的双向one-to-many映射关系的实现
在项目中用到了一对多的实体类关系映射,之前接触的都是基于配置文件的映射实现,但是公司的大部分都是基于注解的,因此自己参考之前的代码捣鼓了基于注解的一对多的映射关系实现。
背景:
一的一端:QingAoCenterInfo:青奥场所信息,
多的一端:QingAoPlaceInfo:青奥场馆信息,
其中一个青奥场所下可以包含多个青奥场馆
one端:QingAoCenterInfo,持有QingAoPlaceInfo的List引用,
通过注解@OneToMany(mappedBy="qingAoCenterInfo",cascade= CascadeType.ALL)
mappedBy:定义类之间的双向关系。如果类之间是单向关系,不需要提供定义,如果类和类之间形成双向关系,我们就需要使用这个属性进行定义, 否则可能引起数据一致性的问题。要由One的一方指向Many的一方,并且,这个属性应该等于Many的一方中含有One类的属性的属性名,否则会出错啦
cascade:CascadeType[]类型。该属性定义类和类之间的级联关系。
定义的级联关系将被容器视为对当前类对象及其关联类对象采取相同的操作,而且这种关系是递归调用的。
举个例子:Order 和OrderItem有级联关系,那么删除QingAoCenterInfo时将同时删除它所对应的QingAoPlaceInfo对象。而如果QingAoPlaceInfo还和其他的对象之间有级联关系,那么这样的操作会一直递归执行下去。
cascade的值只能从CascadeType.PERSIST(级联新建)、CascadeType.REMOVE(级联删除)、CascadeType.REFRESH(级联刷新)、CascadeType.MERGE(级联更新)中选择一个或多个。还有一个选择是使用CascadeType.ALL,表示选择全部四项。
- package com.yuqiaotech.nttelcom.model;
- import java.util.Date;
- import java.util.List;
- import javax.persistence.CascadeType;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.OneToMany;
- import javax.persistence.Table;
- /**
- * 青奥重点场所信息表。
- *
- */
- @Entity(name="QING_AO_CENTER_INFO")
- @Table(name="QING_AO_CENTER_INFO")
- public class QingAoCenterInfo {
- private Long id;
- private String centerName; //重点场所名称
- private Long alarmNum; //告警数
- private String note; //备注
- private String iconName; //图标名称
- private String cityName; //所在城市
- private String type; //重点场所、活动保障
- private Date createTime;
- private List<QingAoPlaceInfo> qingAoPlaceInfo; //场所拥有的场馆
- @Id
- @GeneratedValue(strategy=GenerationType.AUTO)
- public Long getId() {
- return id;
- }
- public void setId(Long id) {
- this.id = id;
- }
- /**
- * @searchItem
- * displayType="text"
- *
- * 重点场所名称
- * @return
- */
- public String getCenterName() {
- return centerName;
- }
- public void setCenterName(String centerName) {
- this.centerName = centerName;
- }
- /**
- * 告警数
- * @return
- */
- public Long getAlarmNum() {
- return alarmNum;
- }
- public void setAlarmNum(Long alarmNum) {
- this.alarmNum = alarmNum;
- }
- /**
- * 备注
- * @return
- */
- public String getNote() {
- return note;
- }
- public void setNote(String note) {
- this.note = note;
- }
- /**
- * 图标名称
- * @return
- */
- public String getIconName() {
- return iconName;
- }
- public void setIconName(String iconName) {
- this.iconName = iconName;
- }
- public String getCityName() {
- return cityName;
- }
- public void setCityName(String cityName) {
- this.cityName = cityName;
- }
- public String getType() {
- return type;
- }
- public void setType(String type) {
- this.type = type;
- }
- public Date getCreateTime() {
- return createTime;
- }
- public void setCreateTime(Date createTime) {
- this.createTime = createTime;
- }
- @OneToMany(mappedBy="qingAoCenterInfo",cascade= CascadeType.ALL)
- public List<QingAoPlaceInfo> getQingAoPlaceInfo() {
- return qingAoPlaceInfo;
- }
- public void setQingAoPlaceInfo(List<QingAoPlaceInfo> qingAoPlaceInfo) {
- this.qingAoPlaceInfo = qingAoPlaceInfo;
- }
- }
many端:QingAoPlaceInfo,持有QingAoCenterInfo的引用
通过@ManyToOne(fetch=FetchType.LAZY ) @JoinColumn(name="f_center_id")设置关联关系
@ManyToOne指明QingAoPlaceInfo和QingAoCenterInfo之间为多对一关系,多个QingAoPlaceInfo实例关联的都是同一个QingAoCenterInfo对象
fetch和lazy是用来定义级联查询的方式:
fetch:官方文档里对fetch有如下描述,Hibernate3 定义了如下几种抓取策略:
连接抓取(Join fetching):Hibernate 通过在
SELECT
语句使用OUTER JOIN
(外连接)来获得对象的关联实例或者关联集合。批量抓取(Batch fetching):对查询抓取的优化方案,通过指定一个主键或外键列表,Hibernate 使用单条
SELECT
语句获取一批对象实例或集合。
- package com.yuqiaotech.nttelcom.model;
- import java.util.Date;
- import java.util.List;
- import javax.persistence.CascadeType;
- import javax.persistence.Entity;
- import javax.persistence.FetchType;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.JoinColumn;
- import javax.persistence.ManyToOne;
- import javax.persistence.OneToMany;
- import javax.persistence.Table;
- /**
- * 场馆信息。
- *
- */
- @Entity(name="QING_AO_PLACE_INFO")
- @Table(name="QING_AO_PLACE_INFO")
- public class QingAoPlaceInfo {
- private Long id;
- private QingAoCenterInfo qingAoCenterInfo;// 重点场所id
- private String placeName;// 场馆名称
- private String note;// 备注
- private String openStat;// 开通状态
- private Long displayOrder;
- private String cityName;
- private Date createTime;
- private List<QingAoPlaceCdmaSector> qingAoPlaceCdmaSector;//拥有的cdma
- private List<QingAoPlaceLteSector> qingAoPlaceLteSector;//拥有的Lte
- private List<QingAoAp> qingAoAp; //拥有的Ap
- @Id
- @GeneratedValue(strategy = GenerationType.AUTO)
- public Long getId() {
- return id;
- }
- public void setId(Long id) {
- this.id = id;
- }
- @ManyToOne(fetch=FetchType.LAZY )
- @JoinColumn(name="f_center_id")
- public QingAoCenterInfo getQingAoCenterInfo() {
- return qingAoCenterInfo;
- }
- public void setQingAoCenterInfo(QingAoCenterInfo qingAoCenterInfo) {
- this.qingAoCenterInfo = qingAoCenterInfo;
- }
- /**
- * @searchItem
- * displayType="text"
- * 场所名称
- * @return
- */
- public String getPlaceName() {
- return placeName;
- }
- public void setPlaceName(String placeName) {
- this.placeName = placeName;
- }
- public String getNote() {
- return note;
- }
- public void setNote(String note) {
- this.note = note;
- }
- public String getOpenStat() {
- return openStat;
- }
- public void setOpenStat(String openStat) {
- this.openStat = openStat;
- }
- public Long getDisplayOrder() {
- return displayOrder;
- }
- public void setDisplayOrder(Long displayOrder) {
- this.displayOrder = displayOrder;
- }
- public String getCityName() {
- return cityName;
- }
- public void setCityName(String cityName) {
- this.cityName = cityName;
- }
- public Date getCreateTime() {
- return createTime;
- }
- public void setCreateTime(Date createTime) {
- this.createTime = createTime;
- }
- @OneToMany(mappedBy="qingAoPlaceInfo",cascade= CascadeType.ALL)
- public List<QingAoPlaceCdmaSector> getQingAoPlaceCdmaSector() {
- return qingAoPlaceCdmaSector;
- }
- public void setQingAoPlaceCdmaSector(
- List<QingAoPlaceCdmaSector> qingAoPlaceCdmaSector) {
- this.qingAoPlaceCdmaSector = qingAoPlaceCdmaSector;
- }
- @OneToMany(mappedBy="qingAoPlaceInfo",cascade= CascadeType.ALL)
- public List<QingAoPlaceLteSector> getQingAoPlaceLteSector() {
- return qingAoPlaceLteSector;
- }
- public void setQingAoPlaceLteSector(
- List<QingAoPlaceLteSector> qingAoPlaceLteSector) {
- this.qingAoPlaceLteSector = qingAoPlaceLteSector;
- }
- @OneToMany(mappedBy="qingAoPlaceInfo",cascade= CascadeType.ALL)
- public List<QingAoAp> getQingAoAp() {
- return qingAoAp;
- }
- public void setQingAoAp(List<QingAoAp> qingAoAp) {
- this.qingAoAp = qingAoAp;
- }
- }