`
ssydxa219
  • 浏览: 608827 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

Hibernate Annotation几种关联映射

 
阅读更多

Hibernate Annotation几种关联映射

hibernate annotation表关联注解

 
 
一对一外键关联映射 (单向)
@Entity
public class Body {
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="bodyid",unique=true)
//一对一外键关联,使用@OneToOne,并设置了级联操作
//@JoinColum设置了外键的名称为bodyid如果不设置,则默认为heart_id
//外键的值是唯一的(unique),不可重复,与Heart的主键一直
public Heart getHeart() {
return heart;
}
 
@Entity
public class Heart {
private int id ;
private String heartName ;
@Id
@GeneratedValue
public int getId() {
return id;
}
 
一对一外键关联映射 (双向)
@Entity
public class Body {
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="bodyid",unique=true)
//一对一外键关联,使用@OneToOne,并设置了级联操作
//@JoinColum设置了外键的名称为bodyid如果不设置,则默认为heart_id
//外键的值是唯一的(unique),不可重复,与Heart的主键一直
public Heart getHeart() {
return heart;
}
 
@Entity
public class Heart {
private int id ;
private String heartName ;
private Body body ;
@OneToOne (mappedBy="heart",cascade=CascadeType.ALL)
public Body getBody() {
return body;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
//一对一双向关联关系,使用@OneToOne
//注意:需要加上mappedBy="heart",如果不加上的话,
//Heart也会生成一个外键(body_id)
//mapped="heart"需要指向与他关联对象的一个属性
//说明双向关联关系中,有且仅有一端是作为主体(owner)端存在的
//主体端负责维护联接列
//对于不需要维护这种关系的从表则通过mappedBy属性进行声明
//mappedBy的值指向主体的关联属性
//规律:只有是双向关联关系,都加上mapped
//cascade=CascadeType.ALL级联
 
多对一关联映射(多个机构对应一个公司)  
@Entity
public class Organization {
private int id ;
private String orgName ;
 
@Id
@GeneratedValue
public int getId() {
return id;
}
********************************
 
@Entity
public class Company {
private int id ;
private String compayName ;
private Organization org ;
@Id
@GeneratedValue
public int getId() {
return id;
}
@ManyToOne(targetEntity=Organization.class)
@JoinColumn(name="orgid")
//多对一注解@ManyToOne
//targetEntity指定了关联对象
//@JoinColumn(name="orgid")指定生产的外键的字段名,默认是org_id
public Organization getOrg() {
return org;
}
 
一对多关联映射(一个机构对应多个公司)  (单向)
 
 
@Entity
public class Organization {
private int id ;
private String orgName ;
private Set<Company> company ;
@OneToMany
@JoinColumn(name="orgid")
public Set<Company> getCompany() {
return company;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
/**
* 一对多注解@OneToMany(单向)
* 如果只写@OneToMany的话,hibernate会建一张中间表来
* 加上@JoinColumn(name=" orgid"),则不会建中间表,他会在
* 多的一端加上外键orgid,来维护他们之间的关系
*/
 
@Entity
public class Company {
private int id ;
private String compayName ;
@GeneratedValue
public int getId() {
return id;
}
 
 
 
一对多关联映射(一个机构对应多个公司)  (双向)
 
@Entity
public class Organization {
private int id ;
private String orgName ;
private Set<Company> company ;
@OneToMany(mappedBy="org")
@JoinColumn(name="orgid")
/**
* 一对多双向,在一的一端中设置mappedBy
* 说明多的一端为主导
* 如果指定了外键字段名称,则多的一端也需要指定相同的字段名称
*/
public Set<Company> getCompany() {
return company;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
 
 
 
@Entity
public class Company {
private int id ;
private String compayName ;
private Organization org ;
@ManyToOne
@JoinColumn(name="orgid")
/**
* 一对多双向
* 需要指定外键与一的一端给的外键名称一致,@JoinColumn(name=" orgid")
* 也可以不指定,如果在多的一端不指定,则一的一端也不能指定
* 否则为生成两个外键
*/
public Organization getOrg() {
return org;
}
 
多对多关联映射 (单向)
 
@Entity
public class User {
private int id ;
private String username ;
private Set<Role> role = new HashSet<Role>() ;
@Id
@GeneratedValue
public int getId() {
return id;
}
@ManyToMany
/**
* 多对多映射:注解@ManyToMany (单向)
* 默认情况下,hibernate会自动的创建一张中间表,
* 来维护多对多关系
* 默认中间表的名称:user_role中间表,字段的名称user_id role_id
* 如果想更换表名和字段名称,注解如下:
*/
@JoinTable(name="t_u_r",
joinColumns={@JoinColumn(name="u_id")},
inverseJoinColumns={@JoinColumn(name="r_id")}
) public Set<Role> getRole() {
return role;
}
 
 
@Entity
public class Role {
private int id ;
private String roleName ;
@Id
@GeneratedValue
public int getId() {
return id;
}
 
 
多对多关联映射 (双向)
@Entity
public class User {
private int id ;
private String username ;
private Set<Role> role = new HashSet<Role>() ;
@Id
@GeneratedValue
public int getId() {
return id;
}
@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")}
* 指定关联对象的外键
*/
public Set<Role> getRole() {
return role;
}
 
 
@Entity
public class Role {
private int id ;
private String roleName ;
private Set<User> user = new HashSet<User>() ;
@ManyToMany(mappedBy="role" )
/**
* 多对多,双向关联映射
*/
public Set<User> getUser() {
return user;
}
@Id
@GeneratedValue
public int getId() {
return id;
}

 

 

 

 

 

一对一(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 trees; @OneToMany(mappedBy="forestType") public Set getTrees() {// trees的getter,setter方法必须在这里,否则会出错 return trees; } public void setTrees(Set 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 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 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 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 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 getEmployers() { return employers; } .. .. } @JoinTable批注定义了联接表的表名,联接列数组,以及invers联接列数组,后者是关联表中关联到Employee主键的列(the “other side”)。 被关联端不必也不能描述物理映射:只需要一个简单的mappedBy参数,该参数包含了主体端的属性名,这样就绑定了双方的关系。 默认值: 和其它许多批注一样,在多对多关联中很多值是自动生成,党双向多对多关联中没有定义任何物理映射时,Hibernate根据以下规则生成相应的值,关联表名:主表表名+下划线+从表表名,关联到主表的外键名:主表名+下划线+主表中的主键列名,关联到从表的外键名:主表中用于关联的属性名+下划线+从表的主键列名,以上规则对于双向一对多关联同样一样。 以上是整理的一点简单的几种映射,可参考EJB3.pdf中P111——P131,hibernate_annotation.pdf 第二章 在这里没有具体的例子,有很多内容还需要仔细查看文档。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics