一、概述
hibernate中使用兩種方式實現主鍵生成策略,分別是XML生成id和注解方式(@GeneratedValue),下面逐一進行總結。
二、XML配置方法
這種方式是在XX.hbm.xml文件中對generator進行配置,eg:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.test.demo"> <class name="Student"> <id name="id"> <generator class="native"></generator> </id> <property name="name"></property> <property name="age"></property> </class> </hibernate-mapping>
常用的生成策略有以下幾種:
identity:對DB2,Mysql,MS SQL Server等的內置標識字段提供支持,返回的標識符是long,short或者int類型
native:可以是identity類型、sequence類型或者hilo類型,取決於不同的底層數據庫
sequence:在Oracle,SAP DB中使用序列(sequence)
uuid:使用一種128位的UUID算法產生的字符類型標識,像IP地址一樣全網唯一
三、注解方式生成ID:@GeneratorValue
標准的annotation方式的主鍵生成策略如下:
- AUTO:可以是identity類型或者是sequence類型或者是table類型,取決於底層的數據庫

import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity public class Person { private String name; private int age; private int id; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Id @GeneratedValue(strategy=GenerationType.AUTO) public int getId() { return id; } public void setId(int id) { this.id = id; } }
- TABLE:使用表保存id值,即會為應用的表創建一張專門保存id的表

import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.TableGenerator; @Entity public class Person { private String name; private int age; private int id; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Id @TableGenerator(name="personID",table="personID_DB",pkColumnName="key_value",pkColumnValue="pk_value",valueColumnName="person",allocationSize=1) @GeneratedValue(strategy=GenerationType.TABLE,generator="personID") public int getId() { return id; } public void setId(int id) { this.id = id; } }
- IDENTITY:identity column

import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.TableGenerator; @Entity public class Person { private String name; private int age; private int id; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Id @GeneratedValue(strategy=GenerationType.IDENTITY) public int getId() { return id; } public void setId(int id) { this.id = id; } }
- SEQUENCE:sequence
四、聯合主鍵生成策略
有的時候我們需要將一個實體的2個或多個字段聯合起來作為主鍵,就是說,不能有2個或多個對象的這幾個字段值都相同的情況發生。現在我們要將Person字段的id和name字段聯合作為主鍵:
@Entity public class Person { //現在id和name組成聯合主鍵 private int id; private String name; private int age; ... }
- 首先將聯合主鍵的屬性提取出來,重新編寫一個pojo類(原pojo類中的id,name要刪除 並新加入屬性“PersonPK”)
- 新建pojo類必須實現 java.io.Serializable 序列化接口
- 新pojo類要重寫equals和hashCode方法
public class PersonPK implements Serializable { private String name; private int id; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public int hashCode() { return this.name.hashCode(); } @Override public boolean equals(Object obj) { if(obj instanceof PersonPK) { PersonPK pk = (PersonPK)obj; if(this.id == pk.getId() && this.name.equals(pk.getName())) { return true; } } return false; } }
聯合主鍵生成策略XML配置方法:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.test.demo"> <class name="Person"> <composite-id name="personPK" class="com.test.demo.PersonPK"> <key-property name="id"></key-property> <key-property name="name"></key-property> </composite-id> <property name="age" /> </class> </hibernate-mapping>
聯合主鍵ID生成策略的Annotation版本,共有三種方式,前三步驟一樣,另外:
方法1、在新類PersonPK前寫@Embeddable,在原Person類的新屬性PersonPK的get方法前寫@id
@Embeddable public class PersonPK implements Serializable { private static final long serialVersionUID = -7068850328521576106L; private String name; private int id; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public int hashCode() { return this.name.hashCode(); } @Override public boolean equals(Object obj) { if(obj instanceof PersonPK) { PersonPK pk = (PersonPK)obj; if(this.id == pk.getId() && this.name.equals(pk.getName())) { return true; } } return false; } }
Person類中:
@Entity public class Person { private PersonPK personPK; private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Id public PersonPK getPersonPK() { return personPK; } public void setPersonPK(PersonPK personPK) { this.personPK = personPK; } }
方法2、新類無需添加注解,只需在原類Person新屬性PersonPK的get方法前寫@EmbeddID即可
@Entity public class Person { private PersonPK personPK; private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } @EmbeddedId public PersonPK getPersonPK() { return personPK; } public void setPersonPK(PersonPK personPK) { this.personPK = personPK; } }
方法3、新pojo類無需加注解,原pojo類的id,name屬性保留不變,也無需新增“TercherPK”屬性。 只在id,name的get方法前都加@Id,並在原pojo類前加@IdClass(PersonPK.class):
原類Person:
@Entity @IdClass(PersonPK.class) public class Person { private int age; private String name; private int id; @Id public String getName() { return name; } public void setName(String name) { this.name = name; } @Id public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
運行測試程序(針對上述三種方法,測試用例需要稍作修改,這里不在贅述):
public class PersonTest { private static SessionFactory sf=null; @BeforeClass public static void beforeClass() { sf=new AnnotationConfiguration().configure().buildSessionFactory(); } @Test public void test() { PersonPK personPK=new PersonPK(); personPK.setId(1); personPK.setName("xujian"); Person p=new Person(); p.setAge(23); p.setPersonPK(personPK); Session session=sf.openSession(); session.beginTransaction(); session.save(p); //提交事物 session.getTransaction().commit(); session.close(); sf.close(); } @AfterClass public static void afterClass() { sf.close(); } }
可以看到:
生成的Person表中id和name組成聯合主鍵