Hibernate复合主键映射

目 录:

创新互联公司坚持“要么做到,要么别承诺”的工作理念,服务领域包括:成都网站设计、网站建设、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的镇远网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!

1. 实现方式一:将复合主键对应的属性与实体其他普通属性放在一起

2. 实现方式二:将主键属性提取到一个主键类中,实体类只需包含主键类的一个引用

在日常开发中会遇到这样一种情况,数据库中的某张表需要多个字段列才能唯一确定一行记录,这时表需要使用复合主键。面对这样的情况Hibernate为我们提供了两种方式来解决复合主键问题。

方式一:将复合主键对应的属性与实体其他普通属性放在一起

例如实体类People中"id"和"name"属性对应复合主键:

 
 
 
 
  1. /*实体类,使用复合主键必须实现Serializable接口*/ 
  2. public class People implements Serializable  
  3. {  
  4.     private static final long serialVersionUID = -4888836126783955019L;  
  5.       
  6.     private String id;  
  7.     private String name;  
  8.     private int age;  
  9.       
  10.     public People()  
  11.     {  
  12.           
  13.     }  
  14.  
  15.     public String getId()  
  16.     {  
  17.         return id;  
  18.     }  
  19.  
  20.     public void setId(String id)  
  21.     {  
  22.         this.id = id;  
  23.     }  
  24.  
  25.     public String getName()  
  26.     {  
  27.         return name;  
  28.     }  
  29.  
  30.     public void setName(String name)  
  31.     {  
  32.         this.name = name;  
  33.     }  
  34.  
  35.     public int getAge()  
  36.     {  
  37.         return age;  
  38.     }  
  39.  
  40.     public void setAge(int age)  
  41.     {  
  42.         this.age = age;  
  43.     }  
  44.  
  45.     @Override 
  46.     public int hashCode()  
  47.     {  
  48.         final int prime = 31;  
  49.         int result = 1;  
  50.         result = prime * result + ((id == null) ? 0 : id.hashCode());  
  51.         result = prime * result + ((name == null) ? 0 : name.hashCode());  
  52.         return result;  
  53.     }  
  54.  
  55.     @Override 
  56.     public boolean equals(Object obj)  
  57.     {  
  58.         if (this == obj)  
  59.             return true;  
  60.         if (obj == null)  
  61.             return false;  
  62.         if (getClass() != obj.getClass())  
  63.             return false;  
  64.         People other = (People) obj;  
  65.         if (id == null)  
  66.         {  
  67.             if (other.id != null)  
  68.                 return false;  
  69.         }  
  70.         else if (!id.equals(other.id))  
  71.             return false;  
  72.         if (name == null)  
  73.         {  
  74.             if (other.name != null)  
  75.                 return false;  
  76.         }  
  77.         else if (!name.equals(other.name))  
  78.             return false;  
  79.         return true;  
  80.     }  

People.hbm.xml:

 
 
 
 
  1.  
  2.  
  3.  
  4.  
  5.      
  6.          
  7.          
  8.              
  9.              
  10.              
  11.          
  12.  
  13.          
  14.      
  15.  

Hibernate中使用复合主键时需要注意一些规则:

1. 使用复合主键的实体类必须实现Serializable接口。必须实现Serializable接口的原因很简单,我们查找数据的时候是根据主键查找的。打开Hibernate的帮助文档我们可以找到get与load方法的声明形式如下:

Object load(Class theClass,Serializable id)

Object get(Class theClass,Serializable id)

当我们查找复合主键类的对象时,需要传递主键值给get()或load()方法的id参数,而id参数只能接收一个实现了Serializable接口的对象。而复合主键类的主键不是一个属性可以表示的,所以只能先new出复合主键类的实例(例如:new People()),然后使用主键属性的set方法将主键值赋值给主键属性,然后将整个对象传递给get()或load()方法的id参数,实现主键值的传递,所以复合主键的实体类必须实现Serializable接口。

2. 使用复合主键的实体类必须重写equals和hashCode方法。必须重写equals和hashCode方法也很好理解。这两个方法使用于判断两个对象 (两条记录)是否相等的。为什么要判断两个对象是否相等呢?因为数据库中的任意两条记录中的主键值是不能相同的,所以我们在程序中只要确保了两个对象的主键值不同就可以防止主键约束违例的错误出现。也许这里你会奇怪为什么不使用复合主键的实体类不重写这两个方法也没有主键违例的情况出现,这是因为使用单一主键方式,主键值是Hibernate来维护的,它会确保主键不会重复,而复合主键方式,主键值是编程人员自己维护的,所以必须重写equals和hashCode方法用于判断两个对象的主键是否相同。

3. 重写的equals和hashCode方法,只与主键属性有关,普通属性不要影响这两个方法进行判断。这个原因很简单,主键才能决定一条记录,其他属性不能决定一条记录。

保存测试:

 
 
 
 
  1. public class Client  
  2. {  
  3.     public static void main(String[] args)  
  4.     {  
  5.         Session session = HibernateUtil.getSessionFactory().openSession();  
  6.         Transaction tx = null;  
  7.           
  8.         try 
  9.         {  
  10.             tx = session.beginTransaction();  
  11.               
  12.             People people = new People();  
  13.             /*主键值由我们自己维护*/ 
  14.             people.setId("123456");  
  15.             people.setName("zhangsan");  
  16.             people.setAge(40);  
  17.               
  18.             session.save(people);  
  19.               
  20.             tx.commit();  
  21.         }  
  22.         catch (Exception e)  
  23.         {  
  24.             if(tx != null)  
  25.             {  
  26.                 tx.rollback();  
  27.             }  
  28.               
  29.             e.printStackTrace();  
  30.         }  
  31.         finally 
  32.         {  
  33.             session.close();  
  34.         }  
  35.     }  

看看数据库:

数据被正确的插入到数据库中了。

读取数据测试:

 
 
 
 
  1. public class Client  
  2. {  
  3.     public static void main(String[] args)  
  4.     {  
  5.         Session session = HibernateUtil.getSessionFactory().openSession();  
  6.         Transaction tx = null;  
  7.           
  8.         try 
  9.         {  
  10.             tx = session.beginTransaction();  
  11.               
  12.             /*查询复合主键对象,需要先构建主键*/ 
  13.             People peoplePrimaryKey = new People();  
  14.             peoplePrimaryKey.setId("123456");  
  15.             peoplePrimaryKey.setName("zhangsan");  
  16.               
  17.             /*然后将构建的主键值传入get方法中获取对应的People对象*/ 
  18.             People people = (People)session.get(People.class, peoplePrimaryKey);  
  19.               
  20.             System.out.println("people age is:"+people.getAge());  
  21.               
  22.             tx.commit();  
  23.         }  
  24.         catch (Exception e)  
  25.         {  
  26.             if(tx != null)  
  27.             {  
  28.                 tx.rollback();  
  29.             }  
  30.               
  31.             e.printStackTrace();  
  32.         }  
  33.         finally 
  34.         {  
  35.             session.close();  
  36.         }  
  37.     }  

控制台输出:

people age is:40

可以看到数据成功的取出了。

方式二:将主键属性提取到一个主键类中,实体类只需包含主键类的一个引用。

主键类:

 
 
 
 
  1. /*必须实现Serializable接口*/ 
  2. public class PeoplePrimaryKey implements Serializable  
  3. {  
  4.     private static final long serialVersionUID = -1190986010439330142L;  
  5.       
  6.     /*复合主键值*/ 
  7.     private String id;  
  8.     private String name;  
  9.       
  10.     public PeoplePrimaryKey()  
  11.     {  
  12.           
  13.     }  
  14.       
  15.     /*复合主键值的get和set方法*/ 
  16.     public String getId()  
  17.     {  
  18.         return id;  
  19.     }  
  20.  
  21.     public void setId(String id)  
  22.     {  
  23.         this.id = id;  
  24.     }  
  25.  
  26.     public String getName()  
  27.     {  
  28.         return name;  
  29.     }  
  30.  
  31.     public void setName(String name)  
  32.     {  
  33.         this.name = name;  
  34.     }  
  35.  
  36.     @Override 
  37.     public int hashCode()  
  38.     {  
  39.         final int prime = 31;  
  40.         int result = 1;  
  41.         result = prime * result + ((id == null) ? 0 : id.hashCode());  
  42.         result = prime * result + ((name == null) ? 0 : name.hashCode());  
  43.         return result;  
  44.     }  
  45.  
  46.     @Override 
  47.     public boolean equals(Object obj)  
  48.     {  
  49.         if (this == obj)  
  50.             return true;  
  51.         if (obj == null)  
  52.             return false;  
  53.         if (getClass() != obj.getClass())  
  54.             return false;  
  55.         PeoplePrimaryKey other = (PeoplePrimaryKey) obj;  
  56.         if (id == null)  
  57.         {  
  58.             if (other.id != null)  
  59.                 return false;  
  60.         }  
  61.         else if (!id.equals(other.id))  
  62.             return false;  
  63.         if (name == null)  
  64.         {  
  65.             if (other.name != null)  
  66.                 return false;  
  67.         }  
  68.         else if (!name.equals(other.name))  
  69.             return false;  
  70.         return true;  
  71.     }  

实体类:

 
 
 
 
  1. public class People  
  2. {  
  3.     /*持有主键类的一个引用,使用该引用作为这个类的OID*/ 
  4.     private PeoplePrimaryKey peoplePrimaryKey;  
  5.     private int age;  
  6.       
  7.     public People()  
  8.     {  
  9.           
  10.     }  
  11.       
  12.     public PeoplePrimaryKey getPeoplePrimaryKey()  
  13.     {  
  14.         return peoplePrimaryKey;  
  15.     }  
  16.  
  17.     public void setPeoplePrimaryKey(PeoplePrimaryKey peoplePrimaryKey)  
  18.     {  
  19.         this.peoplePrimaryKey = peoplePrimaryKey;  
  20.     }  
  21.  
  22.     public int getAge()  
  23.     {  
  24.         return age;  
  25.     }  
  26.  
  27.     public void setAge(int age)  
  28.     {  
  29.         this.age = age;  
  30.     }  

People.hbm.xml文件稍有一点变动:

 
 
 
 
  1.  
  2.  
  3.  
  4.  
  5.      
  6.          
  7.          
  8.          
  9.              
  10.              
  11.              
  12.          
  13.  
  14.          
  15.      
  16.  

场景测试与方式一大同小异这里不再举例了。主键类为什么实现Serializable接口和为什么重写equals和hashCode方法上面已经解释的很清楚了。

网站题目:Hibernate复合主键映射
URL网址:http://www.shufengxianlan.com/qtweb/news14/516614.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联