文档章节

Hibernate Annotation 关联映射

mr桀骜不驯
 mr桀骜不驯
发布于 2013/04/07 15:08
字数 2761
阅读 766
收藏 6
hibernate Annotation标签的使用:
1.带注释的持久性类也是普通 POJO,它们只是具备了持久性注释的普通 POJO 。
2.事实上,您既可以保持字段的持久性(注释写在成员变量之上),也可以保持属性(注释写在getter方法之上)的持久性。
常用的hibernate annotation标签如下:
@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)



Hibernate Annotation几种关联映射

一对一(One-To-One)

使用@OneToOne注解建立实体Bean之间的一对一关联。一对一关联有三种情况:(1).关联的实体都共享同样的主键,(2).其中一个实体通过外键关联到另一个实体的主键(注意要模拟一对一关联必须在外键列上添加唯一约束),(3).通过关联表来保存两个实体之间的连接关系(要模拟一对一关联必须在每一个外键上添加唯一约束)。

 

1.共享主键的一对一关联映射:

@Entity

@Table(name="Test_Body")

public class Body {

   private Integer id;

   private Heart heart;

   @Id

   public Integer getId() {

      return id;

   }

   public void setId(Integer id) {

      this.id = id;

   }

   @OneToOne

   @PrimaryKeyJoinColumn

   public Heart getHeart() {

      return heart;

   }

   public void setHeart(Heart heart) {

      this.heart = heart;

   }

}

@Entity

@Table(name="Test_Heart")

public class Heart {

   private Integer id;

   @Id

   public Integer getId() {

      return id;

   }

   public void setId(Integer id) {

      this.id = id;

   }

}

通过@PrimaryKeyJoinColumn批注定义了一对一关联

 

2.使用外键进行实体一对一关联:

@Entity

@Table(name="Test_Trousers")

public class Trousers {

   @Id

   public Integer id;

   @OneToOne

   @JoinColumn(name = "zip_id")

   public TrousersZip zip;

}

@Entity

@Table(name="Test_TrousersZip")

public class TrousersZip {

   @Id

   public Integer id;

   @OneToOne(mappedBy = "zip")

   public Trousers trousers;

}

上面的例子是指Trousers通过Trousers的外键列zip_id和TrousersZip关联,@JoinColumn批注定义了联接列,该批注和@Column批注有点类似,但是多了一个名为referencedColumnName的参数。该参数定义了所关联目标实体中的联接列,注意,当referencedColumnName关联到非主键列的时候,关联的目标类必须实现Serializable,还要注意的是所映像的属性对应单个列(否则映射无效)

一对一关联可能是双向的,在双向关联中,有且仅有一端作为主体(owner)端存在:主体端负责维护联接列(即更新),对于不需要维护这种关系的从表则通过mappedNy属性进行声明。mappedBy的值指向主体的关联属性。例子中,mappedBy的值为zip。最后,不必也不能再在被关联端(ownedside)定义联接列了,因为已经在主体端声明了。

如果在主体没有声明@JoinColumn,系统自动进行处理:在主表(owner table)中将创建联接列,列名为:主体的关联属性名+下划线+被关联端的主键列名。上面的例子中是zip_id,因为Trousers中的关联属性名为zip,TrousersZip的主键是id。

 

3.通过关联表定义一对一关联

@Entity

@Table(name="Test_People")

public class People {

   @Id

   public Integer id;

   @OneToOne

   @JoinTable(name ="TestPeoplePassports",

      joinColumns =@JoinColumn(name="people_fk"),

      inverseJoinColumns =@JoinColumn(name="passport_fk")

   )

   public Passport passport;

}

@Entity

@Table(name="Test_Passport")

public class Passport {

   @Id

   public Integer id;

   @OneToOne(mappedBy = "passport")

   public People people;

}

People通过名为TestPeoplePassports的关联表和Passport关联。该关联表拥有名为passport_fk的外键列,该外键指向Passport表,该信息定义为inverseJoinColoumns的属性值,而people_fk外键列指向People表,该信息定义为joinColumns的属性值。

这种关联可能是双向的,在双向关联中,有且仅有一端作为主体(owner)端存在:主体端负责维护联接列(即更新),对于不需要维护这种关系的从表则通过mappedNy属性进行声明。mappedBy的值指向主体的关联属性。例子中,mappedBy的值为passport。最后,不必也不能再在被关联端(ownedside)定义联接列了,因为已经在主体端声明了。

以上是一对一关联的三种形式,下面介绍多对一关联。

 

 

 

多对一(Many-to-One)

使用@ManyToOne批注来实现多对一关联。

@ManyToOne批注有一个名为targetEntity的参数,该参数定义了目标实体名,通常不需要定义该参数,因为在大部分情况下默认值(表示关联关系的属性类型)就可以很好的满足需求了。不过下面这种情况下这个参数就显得有意义了:使用接口作为返回值而不是常见的实体。

@ManyToOne(targetEntity=CompanyImpl.class)

@JoinColoumn(name=”COPM_ID”)

Public Company getCompany(){

   return company;

}

多对一的配置方式有两种:(1)通过@JoinColoumn映像(2)通过关联表的方式来映像

 

(1)通过@JoinColoumn映射

SRD Framework中Company,Category例子:

Company:

@ManyToOne

   @JoinColumn(name = "CATEGORY_OPTION_ID")

   private Category category = null;

   Category:

@DiscriminatorValue("Category")

public class Category extends Option {

}

(2)通过关联表映射

通过@JoinTable批注定义关联表,该关联表包含了指回实体表的外键(通过@JoinTable.joinColoumns)以及指向目标实体表的外键(通过@JoinTable.inverseJoinColoumns)

@Entity

@Table(name="Test_TreeType")

public class TreeType {

   private Integer id;

   private String name;

   private ForestType forestType;

   @ManyToOne(fetch = FetchType.LAZY)

   @JoinTable(name="Test_Tree_Forest",

      joinColumns = @JoinColumn(name="tree_id"),

      inverseJoinColumns = @JoinColumn(name="forest_id") )

public ForestType getForestType() {// forestType的getter,setter方法必须在这里,否则会出错

      return forestType;

   }

   public void setForestType(ForestType forestType) {

      this.forestType = forestType;

   }

   @Id

   @GeneratedValue

   public Integer getId() {

      return id;

   }

   public void setId(Integer id) {

      this.id = id;

   }

   public String getName() {

      return name;

   }

   public void setName(String name) {

      this.name = name;

   }

}

@Entity

@Table(name="Test_ForestType")

public class ForestType {

   private Integer id;

   private String name;

   private Set<TreeType> trees;

   @OneToMany(mappedBy="forestType")

public Set<TreeType> getTrees() {// trees的getter,setter方法必须在这里,否则会出错

      return trees;

   }

   public void setTrees(Set<TreeType> trees) {

      this.trees = trees;

   }

   @Id @GeneratedValue

   public Integer getId() {

      return id;

   }

   public void setId(Integer id) {

      this.id = id;

   }

   public String getName() {

      return name;

   }

   public void setName(String name) {

      this.name = name;

   }

}

 

一对多(One-to-Many)

使用@OneToMany批注可定义一对多关联,一对多关联可以是双向关联。

在EJB3规范中多对一这端几乎总是双向关联中的主体(owner)端,而一对多这端关联批注为@OneToMany(mappedBy...)

@Entity

Public class Troop{

   @OneToMany(mappedBy=”troop”)

Public Set<Soldier> getSoldiers(){

......

}

@Entity

Public class Soldier{

   @ManyToOne

   @JoinColumn(name=”troop_fk”)

Public Troop getTroop(){

......

}

Troop通过troop属性和Soldier建立一对多的双向关联,在mappedBy端不必也不能再定义任何物理映射。

对于一对多的双向映射,如果要一对多这一端维护关联关系,你需要删除mappedBy元素并将多对一这端的@JoinColoumn的insertable和updatabel设置为false。这种方案不会得到什么明显的优化,而且还会增加一些附加的UPDATE语句。

 

单向:

通过在被拥有的实体端(owned entity)增加一个外键列来实现一对多单向关联是很少见的,也是不推荐的,建议通过一个联接表来实现这种关联(下面会讲到)。

@JoinColoumn批注来描述这种单向关联关系

@Entity

Public class Customer{

   @OneToMany

@JoinColoumn(name=”CUST_ID”)

Public Set<ticket> getTickets() {

......

}

@Entity

Public class Ticket{

   ...

}

Customer通过CUST_ID列和Ticket建立了单向关联关系

通过关联表处理单向关联:

通过联接表处理单向一对多关联是首选方式,这种关联通过@JoinTable批注进行描述

@Entity

Public class Trainer{

@OneToMany

@JoinTable(

   name = "TrainedMonkeys",

   jonColumns = {@JoinColumn(name = "trainer_id")},

   inverseJoinColumns = @JoinColumn(name = "monkey_id")

   )

public Set<Monkey> getTrainedMonkeys() {

      return trainedMonkeys;

   }

......

}

@Entity

public class Monkey {

...//no bidir

}

上面这个例子中,Trainer通过TrainedMonkeys表和Monkey建立了单向关联,其中外键trainer_id关联到Trainer(joinColoumn),而外键monkey_id关联到Monkey(inversejionColoumns)

默认处理机制:

通过联接表来建立单向一对多关联不需要描述任何物理映像,表名由以下三个部分组成:主表(ownertable)表名+从表(the other side table)表名,指向主表的外键名:主表表名+下划线+主表主键列名,指向从表的外键名:主表所对应实体的属性名+下划线+从表主键列名,指向从表的外键定义为唯一约束,用来表示一对多的关联关系。

@Entity

public class Trainer{

   @OneToMany

   Public Set<Tiger> getTrainedTigers(){

... ...

}

@Entity

public class Tiger{

.. ..//no bidir

}

上面这个例子中,Trainer和Tiger通过联接表Trainer_Tiger建立单向关联关系,其中外键trainer_id关联到Trainer,而外键trainedTigers_id关联到Tiger

 

多对多(Many-to-Many)

使用@ManyToMany批注可定义多对多关联,同时,你也许要通过批注@JoinTable描述关联表和关联条件。如果是双向关联,其中一段必须定义为Owner,另一端必须定义为inverse(在对关联表进行更新操作时这一端将被忽略)

@Entity

public class Employer implements Serializable {

   private Integer id;

   private Collection employees;

   @ManyToMany(

targetEntity = org.hibernate.test.annotations.manytomany.Employee.class,

      cascade = {CascadeType.PERSIST, CascadeType.MERGE}

   )

   @JoinTable(

         name = "EMPLOYER_EMPLOYEE",

         joinColumns = {@JoinColumn(name = "EMPER_ID")},

         inverseJoinColumns = {@JoinColumn(name = "EMPEE_ID")}

   )

   public Collection getEmployees() {

      return employees;

   }

...

}

@Entity()

public class Employee implements Serializable {

   @ManyToMany(

         cascade = {CascadeType.PERSIST, CascadeType.MERGE},

         mappedBy = "employees"

         targetEntity = Employer.class

   )

public Collection<Employer> getEmployers() {

      return employers;

   }

.. ..

}

@JoinTable批注定义了联接表的表名,联接列数组,以及invers联接列数组,后者是关联表中关联到Employee主键的列(the “other side”)。

被关联端不必也不能描述物理映射:只需要一个简单的mappedBy参数,该参数包含了主体端的属性名,这样就绑定了双方的关系。

默认值:

和其它许多批注一样,在多对多关联中很多值是自动生成,党双向多对多关联中没有定义任何物理映射时,Hibernate根据以下规则生成相应的值,关联表名:主表表名+下划线+从表表名,关联到主表的外键名:主表名+下划线+主表中的主键列名,关联到从表的外键名:主表中用于关联的属性名+下划线+从表的主键列名,以上规则对于双向一对多关联同样一样。

© 著作权归作者所有

mr桀骜不驯
粉丝 7
博文 12
码字总数 4596
作品 0
广州
程序员
私信 提问
Hibernate-Annotation

课程地址 使用hibernate注解的目的 为了简化ORM映射文件(*.hbm)繁琐的配置。 注解需要做的是映射文件要做的。 JPA与Hibernate Java Persistence API Java持久化接口 JPA是标准接口,HIberna...

FutaoSmile丶
2017/09/28
0
0
Hibernate Annotation笔记

(1) 简介: 在过去几年里,Hibernate不断发展,几乎成为Java数据库持久性的事实标准。它非常强大、灵活,而且具备了优异的性能。在本文中,我们将了解如何使用Java 5 注释来简化Hibernate代码...

geeksun
2012/05/14
147
0
Hibernate的annotation

@Controller控制器 @Service @Conponent 组件 @Repository Dao访问层 @Entity 实体 @Table 实体mapping表 @Column 属性mapping列 ----> 不需要Mapping的时候用@Transient @Id mapping主键属性......

geeksun
2012/05/11
149
0
【转载】Hibernate3注解

Hibernate3注解 收藏 1、@Entity(name="EntityName") 必须,name为可选,对应数据库中一的个表 2、@Table(name="",catalog="",schema="") 可选,通常和@Entity配合使用,只能标注在实体的class定......

youfen
2018/08/27
22
0
springside3里面的hibernate

springside3 里面的 hibernate 以 springside3 里面的 mini-web 为例子来分析。 src/main/java 目录结构 src/test/java 目录结构 如果需要更换数据库的话,就要改 2 个文件即可。 applicatio...

晨曦之光
2012/05/23
500
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring boot 静态资源访问

0. 两个配置 spring.mvc.static-path-patternspring.resources.static-locations 1. application中需要先行的两个配置项 1.1 spring.mvc.static-path-pattern 这个配置项是告诉springboo......

moon888
今天
3
0
hash slot(虚拟桶)

在分布式集群中,如何保证相同请求落到相同的机器上,并且后面的集群机器可以尽可能的均分请求,并且当扩容或down机的情况下能对原有集群影响最小。 round robin算法:是把数据mod后直接映射...

李朝强
今天
4
0
Kafka 原理和实战

本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/bV8AhqAjQp4a_iXRfobkCQ 作者简介:郑志彬,毕业于华南理工大学计算机科学与技术(双语班)。先后从事过电子商务、开放平...

vivo互联网技术
今天
19
0
java数据类型

基本类型: 整型:Byte,short,int,long 浮点型:float,double 字符型:char 布尔型:boolean 引用类型: 类类型: 接口类型: 数组类型: Byte 1字节 八位 -128 -------- 127 short 2字节...

audience_1
今天
9
0
太全了|万字详解Docker架构原理、功能及使用

一、简介 1、了解Docker的前生LXC LXC为Linux Container的简写。可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。相当于C++中的NameSpa...

Java技术剑
今天
27
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部