[转]hiberante中使用复合主键

 
hiberante中使用复合主键

对于新系统的设计开发而言,我们应尽量避免在库表中引入与业务逻辑相关的主键关系。将业务逻辑主键引入库表,以后业务逻辑的变化,将很可能对底层数据库结构产生连带影响。复合主键的引入,很大程度上意味着业务逻辑已经侵入到数据存储逻辑之中。因此,应尽量避免。但实际情况中,我们必须面对遗留系统的旧表开发,这时,对现有复合主键的支持就非常必要。

hibernate中,通过composite-id节点对复合主键进行定义。
我们可以通过两种形式确定主键:
1)基于实体类属性的复合主键
2)基于主键类的复合主键

下面通过例子看一下两种方式的用法。

我们建一个用户表user(firstname, lastname, age),以firstname, lastname作为复合主键。建表语句:
CREATE TABLE `hbm_test`.`user` (
  `firstname` VARCHAR(50) NOT NULL DEFAULT '',
  `lastname` VARCHAR(50) NOT NULL DEFAULT '',
  `age` INTEGER UNSIGNED DEFAULT 0,
  PRIMARY KEY(`firstname`, `lastname`)
)
ENGINE = InnoDB;

1)基于实体类属性的复合主键

映射文件如下:

xml 代码
  1. <class name="User" table="user">  
  2.   
  3. <composite-id>  
  4.  <key-property  
  5.   name="Lastname"  
  6.   column="lastname"  
  7.   type="string"  
  8.  />  
  9.  <key-property  
  10.   name="Firstname"  
  11.   column="firstname"  
  12.   type="string"  
  13.  />  
  14. </composite-id>  
  15.   
  16. <property  
  17.  name="Age"  
  18.  column="age"  
  19.  type="integer"  
  20.  not-null="false"  
  21.  length="10"  
  22. />  
  23.   
  24. </class>  
  25.   

通过composite-id节点声明了一个复合主键,是由“firstname" "lastname"组成。

实体类User中包含了复合主键firstname lastname,hibernate要求复合主键类实现equals hashCode,以作为不同数据间的识别的标志。

java 代码
  1. public class User implements Serializable{   
  2.  private String firstname;   
  3.  private String lastname;   
  4.  private int age;   
  5.     
  6.  public int getAge() {   
  7.   return age;   
  8.  }   
  9.  public void setAge(int age) {   
  10.   this.age = age;   
  11.  }   
  12.  public String getFirstname() {   
  13.   return firstname;   
  14.  }   
  15.  public void setFirstname(String firstname) {   
  16.   this.firstname = firstname;   
  17.  }   
  18.  public String getLastname() {   
  19.   return lastname;   
  20.  }   
  21.  public void setLastname(String lastname) {   
  22.   this.lastname = lastname;   
  23.  }   
  24.     
  25.  public boolean equals(Object obj){   
  26.   if(!(obj instanceof User)){   
  27.    return false;   
  28.   }else{   
  29.    User user = (User)obj;   
  30.    return new EqualsBuilder().appendSuper(super.equals(obj))   
  31.       .append(this.firstname, user.firstname)   
  32.       .append(this.lastname, user.lastname)   
  33.       .isEquals();   
  34.   }   
  35.  }   
  36.     
  37.  public int hashCode(){   
  38.   return new HashCodeBuilder(-528253723, -475504089)   
  39.      .appendSuper(super.hashCode())   
  40.      .append(this.firstname)   
  41.      .append(this.lastname)   
  42.      .toHashCode();   
  43.  }   
  44. }   
  45.   

EqualsBuilder HashCodeBuilder均为 apache common lang包中的工具类。

对于Session.load方法,我们可将User类对象本身作为查询条件:

java 代码
  1. User user = new User();   
  2. user.setFirstname("hello");   
  3. user.setLastname("world");   
  4. user = (User)session.load(User.class, user);   
  5. System.out.println("age: " + user.getAge());  

2)基于主键类的复合主键

我们可以将主键逻辑加以分离,以一个单独的主键类对复合主键进行描述。
现在把User中的firstname lastname提取到一个独立的主键类UserPK中:

java 代码
  1. public class UserPK implements Serializable{   
  2.  private String firstname;   
  3.  private String lastname;   
  4.  public String getFirstname() {   
  5.   return firstname;   
  6.  }   
  7.  public void setFirstname(String firstname) {   
  8.   this.firstname = firstname;   
  9.  }   
  10.  public String getLastname() {   
  11.   return lastname;   
  12.  }   
  13.  public void setLastname(String lastname) {   
  14.   this.lastname = lastname;   
  15.  }   
  16.     
  17. }   
  18.   

之后修改映射文件的composite-id节点:

xml 代码
  1. <composite-id name="userPk" class="UserPK">  
  2.  <key-property  
  3.   name="Lastname"  
  4.   column="lastname"  
  5.   type="string"  
  6.  />  
  7.  <key-property  
  8.   name="Firstname"  
  9.   column="firstname"  
  10.   type="string"  
  11.  />  
  12. </composite-id>  
  13.   
  14. <property  
  15.  name="Age"  
  16.  column="age"  
  17.  type="integer"  
  18.  not-null="false"  
  19.  length="10"  
  20. />  
  21.   

只是配置了name和class属性,name指定了实体类中的主键类属性名,class指定了主键类类型。

User.java修改如下:

java 代码
  1. public class User implements Serializable{   
  2.  private UserPK userPk;   
  3.  private int age;   
  4.     
  5.  public int getAge() {   
  6.   return age;   
  7.  }   
  8.  public void setAge(int age) {   
  9.   this.age = age;   
  10.  }   
  11.  public UserPK getUserPk() {   
  12.   return userPk;   
  13.  }   
  14.  public void setUserPk(UserPK userPk) {   
  15.   this.userPk = userPk;   
  16.  }   
  17.     
  18. }   

之后,我们即可通过UserPK进行数据查询:

java 代码
  1. UserPK userPk = new UserPK();   
  2. userPk.setFirstname("hello");   
  3. userPk.setLastname("world");   
  4. User user = (User)session.load(User.class, userPk);   
  5. System.out.println("age: " + user.getAge());  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值