hibernate_ID生成策略
increment:主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是:如果当前有多个实例访问同一个数据库,那么由于各个实例各自维护主键状态,不同实例可能生成同样的主键,从而造成主键重复异常。因此,如果同一数据库有多个实例访问,此方式必须避免使用;
采用数据库提供的主键生成机制。如DB2、SQL Server、MySQL中的主键生成机制。
采用数据库提供的sequence 机制生成主键。如Oralce 中的Sequence。
hi/lo 算法实现的主键生成机制,需要额外的数据库表保存主键生成历史状态。
4)seqhilo
与hilo 类似,通过hi/lo 算法实现的主键生成机制,只是主键历史状态保存在Sequence中,适用于支持Sequence的数据库,如Oracle。
由Hibernate基于128 位唯一值产生算法生成16 进制数值(编码后以长度32 的字符串表示)作为主键。(跨数据库)
由Hibernate基于128 位唯一值产生算法生成16 进制数值(编码后以长度32 的字符串表示)作为主键。(跨数据库)
很少用;
根据数据库选择自动递增算法,常用;(跨数据库)
主键由外部程序负责生成,无需hibernate参与;
很少用;
使用外部表的字段作为主键。
主键按数值顺序递增。此方式的实现机制为在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键。这种方式可能产生的问题是:如果当前有多个实例访问同一个数据库,那么由于各个实例各自维护主键状态,不同实例可能生成同样的主键,从而造成主键重复异常。因此,如果同一数据库有多个实例访问,此方式必须避免使用。
一般而言,利用uuid.hex方式生成主键将提供最好的性能和数据库平台适应性。
另外由于常用的数据库,如Oracle、DB2、SQLServer、MySql 等,都提供了易用的主键生成机制(Auto-Increase 字段或者Sequence)。我们可以在数据库提供的主键生成机制上,采用generator-class=native的主键生成方式。
hibernate 的说明如下:
不过值得注意的是,一些数据库提供的主键生成机制在效率上未必最佳,大量并发insert数据时可能会引起表之间的互锁。数据库提供的主键生成机制,往往是通过在一个内部表中保存当前主键状态(如对于自增型主键而言,此内部表中就维护着当前的最大值和递增量),之后每次插入数据会读取这个最大值,然后加上递增量作为新记录的主键,之后再把这个新的最大值更新回内部表中,这样,一次Insert操作可能导致数据库内部多次表读写操作,同时伴随的还有数据的加锁解锁操作,这对性能产生了较大影响。因此,对于并发Insert要求较高的系统,推荐采用uuid.hex 作为主键生成机制。
路径:hibernate-distribution-3.3.2.GA/documentation/manual/zh-CN/html_single/index.html#mapping-declaration-id
截图:
uuid XML 配置:
1 <id name="id" column="id"> 2 <generator class="uuid"/> 3 </id>
对应的JavaBean用String类型:
1 private String id; 2 public String getId() { 3 return id; 4 } 5 6 public void setId(String id) { 7 this.id = id; 8 }
native XML 配置:
<id name="id" column="id"> <generator class="native"/> </id>
对应的JavaBean用Integer/int类型:
1 private Integer id; 2 public Integer getId() { 3 return id; 4 } 5 6 public void setId(Integer id) { 7 this.id = id; 8 }
用 MySQL 数据库,hibernate自动生成的建_student表的语句:
连接Oracle数据库进行测试:
1、重新在 hibernate.cfg.xml文件中修改Oracle的连接配置,具体配置驱动、url、username、password的配置参考:
hibernate-distribution-3.3.2.GA\project\etc\hibernate.properties
2、java bean的属性配置要符合oracle表和字段的命名规范;
3、ID 配置:
XML 的跟上面的一样;
注解:默认就是AUTO(相当于native),可以不用写,此时ID生成的sequence是hibernate_sequence;
还有 IDENTITY(只能用在MySQL和SQL Server等支持IDENTITY的数据库中,Oracle就用不了)、SEQUENCE、TABLE
@Id @GeneratedValue(strategy=GenerationType.AUTO) public Integer getId() { return id; }
3.1、如果要为 model ID 指定确定的sequence,而不是去用默认的 hibernate_sequence,配置如下:
注解:
model头:name 表示这个sequence生成器的名字,sequenceName 是指明序列在数据库中的名字
@Entity @SequenceGenerator(name="teacherSEQ",sequenceName="teacherSEQ_DB")
ID上的配置:
@Id @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="teacherSEQ") public Integer getId() { return id; }
XML:在 hibernate.cfg.xml 中的配置
1 <hibernate-mapping> 2 <class name="..." table="..." schema="..."> 3 <id name="userId" type="java.lang.Integer"> 4 <column name="USER_ID" precision="9" scale="0" /> 5 <generator class="sequence"> 6 <param name="sequence">Student_SEQ</param> 7 </generator> 8 </id> 9 <property ... /> 10 </class> 11 </hibernate-mapping>
3.2、复杂一点的主键生成器——TableGenerator
1 @javax.persistence.TableGenerator( 2 name="Teacher_GEN",//生成器名 3 table="GENERATOR_TABLE",//表名 4 pkColumnName = "pk_key",//第一个字段,key值 5 valueColumnName = "pk_value",//第二个字段,value值 6 pkColumnValue="Teacher",//一条记录的第一个字段 7 allocationSize=1//增量 8 ) 9 @Id 10 @GeneratedValue(strategy=GenerationType.TABLE,generator="Teacher_GEN") 11 public Integer getId() { 12 return id; 13 }
初次使用该生成器,生成器找到对应的记录,返回value值1,同时value加上对应的增量。
3.3 联合主键
XML:一个表中的两个字段做主键,例子中取Student中的id、name做主键,创建一个StudentPK做主键类,在Student中配置好联合主键
Student
package com.bjsxt.hibernate; public class Student { private StudentPK pk; private Integer age; public StudentPK getPk() { return pk; } public void setPk(StudentPK pk) { this.pk = pk; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
StudentPK 需要实现Serializable接口,重写hashCode()和equals()方法
1 package com.bjsxt.hibernate; 2 3 import java.io.Serializable; 4 5 public class StudentPK implements Serializable{ 6 7 private static final long serialVersionUID = -7950018142709463675L; 8 9 private Integer id; 10 11 private String name; 12 13 public Integer getId() { 14 return id; 15 } 16 17 public void setId(Integer id) { 18 this.id = id; 19 } 20 21 public String getName() { 22 return name; 23 } 24 25 public void setName(String name) { 26 this.name = name; 27 } 28 29 @Override 30 public boolean equals(Object o) { 31 if(o instanceof StudentPK){ 32 StudentPK pk = (StudentPK)o; 33 if(this.id == pk.getId() && this.name.equals(pk.getName())){ 34 return true; 35 } 36 } 37 return false; 38 } 39 40 @Override 41 public int hashCode() { 42 return this.name.hashCode(); 43 } 44 }
Student.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 6 <hibernate-mapping package="com.bjsxt.hibernate"> 7 <class name="Student" table="student"> 8 <composite-id name="pk" class="com.bjsxt.hibernate.StudentPK"> 9 <key-property name="id" /> 10 <key-property name="name" /> 11 </composite-id> 12 <property .../> 13 </class> 14 </hibernate-mapping>
插入操作:
1 @Test 2 public void testStudentSave(){ 3 StudentPK pk = new StudentPK(); 4 pk.setId(1); 5 pk.setName("zhangsan"); 6 Student s = new Student(); 7 s.setPk(pk); 8 ... 9 }
Annotation:
第一种方法:将组件类注解为@Embeddable,并将组件的属性注解为@Id;
第二种方法:将组件的属性注解为@EmbeddedId;
第三种方法:将类注解为@IdClass,并将该实体中所有属于主键的属性都注解为@Id;
3种方法的主键类同样要需要实现Serializable接口,重写hashCode()和equals()方法。
第一种方法例子:
TeacherPK
1 package com.bjsxt.hibernate; 2 3 import java.io.Serializable; 4 5 @Embeddable 6 public class TeacherPK implements Serializable{ 7 8 private static final long serialVersionUID = -3972276136768456123L; 9 10 private Integer id; 11 12 private String name; 13 14 public Integer getId() { 15 return id; 16 } 17 18 public void setId(Integer id) { 19 this.id = id; 20 } 21 22 public String getName() { 23 return name; 24 } 25 26 public void setName(String name) { 27 this.name = name; 28 } 29 30 @Override 31 public boolean equals(Object o) { 32 if(o instanceof StudentPK){ 33 StudentPK pk = (StudentPK)o; 34 if(this.id == pk.getId() && this.name.equals(pk.getName())){ 35 return true; 36 } 37 } 38 return false; 39 } 40 41 @Override 42 public int hashCode() { 43 return this.name.hashCode(); 44 } 45 46 }
Teacher
1 package com.bjsxt.hibernate; 2 3 import java.util.Date; 4 5 import javax.persistence.EmbeddedId; 6 import javax.persistence.Entity; 7 import javax.persistence.EnumType; 8 import javax.persistence.Enumerated; 9 import javax.persistence.GeneratedValue; 10 import javax.persistence.GenerationType; 11 import javax.persistence.Id; 12 import javax.persistence.IdClass; 13 import javax.persistence.SequenceGenerator; 14 import javax.persistence.Temporal; 15 import javax.persistence.TemporalType; 16 17 @javax.persistence.TableGenerator( 18 name="Teacher_GEN",//生成器名 19 table="GENERATOR_TABLE",//表名 20 pkColumnName = "pk_key",//第一个字段,key值 21 valueColumnName = "pk_value",//第二个字段,value值 22 pkColumnValue="Teacher",//记录值 23 allocationSize=1//增量 24 ) 25 26 @Entity 27 @SequenceGenerator(name="teacherSEQ",sequenceName="teacherSEQ_DB") 28 public class Teacher { 29 private TeacherPK pk; 30 31 private String title; 32 33 private Date birthday; 34 35 private ZhiCheng zhicheng; 36 37 public String getTitle() { 38 return title; 39 } 40 41 @Id 42 public TeacherPK getPk() { 43 return pk; 44 } 45 46 public void setPk(TeacherPK pk) { 47 this.pk = pk; 48 } 49 50 public void setTitle(String title) { 51 this.title = title; 52 } 53 54 @Temporal(TemporalType.DATE) 55 public Date getBirthday() { 56 return birthday; 57 } 58 59 public void setBirthday(Date birthday) { 60 this.birthday = birthday; 61 } 62 63 @Enumerated(value=EnumType.STRING) 64 public ZhiCheng getZhicheng() { 65 return zhicheng; 66 } 67 68 public void setZhicheng(ZhiCheng zhicheng) { 69 this.zhicheng = zhicheng; 70 } 71 72 }
第二种方法例子:
TeacherPK
1 package com.bjsxt.hibernate; 2 3 import java.io.Serializable; 4 5 public class TeacherPK implements Serializable{ 6 7 private static final long serialVersionUID = -3972276136768456123L; 8 9 private Integer id; 10 11 private String name; 12 13 public Integer getId() { 14 return id; 15 } 16 17 public void setId(Integer id) { 18 this.id = id; 19 } 20 21 public String getName() { 22 return name; 23 } 24 25 public void setName(String name) { 26 this.name = name; 27 } 28 29 @Override 30 public boolean equals(Object o) { 31 if(o instanceof StudentPK){ 32 StudentPK pk = (StudentPK)o; 33 if(this.id == pk.getId() && this.name.equals(pk.getName())){ 34 return true; 35 } 36 } 37 return false; 38 } 39 40 @Override 41 public int hashCode() { 42 return this.name.hashCode(); 43 } 44 45 }
Teacher
1 package com.bjsxt.hibernate; 2 3 import java.util.Date; 4 5 import javax.persistence.EmbeddedId; 6 import javax.persistence.Entity; 7 import javax.persistence.EnumType; 8 import javax.persistence.Enumerated; 9 import javax.persistence.GeneratedValue; 10 import javax.persistence.GenerationType; 11 import javax.persistence.Id; 12 import javax.persistence.IdClass; 13 import javax.persistence.SequenceGenerator; 14 import javax.persistence.Temporal; 15 import javax.persistence.TemporalType; 16 17 @javax.persistence.TableGenerator( 18 name="Teacher_GEN",//生成器名 19 table="GENERATOR_TABLE",//表名 20 pkColumnName = "pk_key",//第一个字段,key值 21 valueColumnName = "pk_value",//第二个字段,value值 22 pkColumnValue="Teacher",//记录值 23 allocationSize=1//增量 24 ) 25 26 @Entity 27 @SequenceGenerator(name="teacherSEQ",sequenceName="teacherSEQ_DB") 28 public class Teacher { 29 private TeacherPK pk; 30 31 private Integer id; 32 33 private String name; 34 35 private String title; 36 37 private Date birthday; 38 39 private ZhiCheng zhicheng; 40 41 public void setName(String name) { 42 this.name = name; 43 } 44 45 public String getTitle() { 46 return title; 47 } 48 49 50 @EmbeddedId 51 public TeacherPK getPk() { 52 return pk; 53 } 54 55 public void setPk(TeacherPK pk) { 56 this.pk = pk; 57 } 58 59 public void setTitle(String title) { 60 this.title = title; 61 } 62 63 @Temporal(TemporalType.DATE) 64 public Date getBirthday() { 65 return birthday; 66 } 67 68 public void setBirthday(Date birthday) { 69 this.birthday = birthday; 70 } 71 72 @Enumerated(value=EnumType.STRING) 73 public ZhiCheng getZhicheng() { 74 return zhicheng; 75 } 76 77 public void setZhicheng(ZhiCheng zhicheng) { 78 this.zhicheng = zhicheng; 79 } 80 81 }
第三种方法例子:
TeacherPK
1 package com.bjsxt.hibernate; 2 3 import java.io.Serializable; 4 5 public class TeacherPK implements Serializable{ 6 7 private static final long serialVersionUID = -3972276136768456123L; 8 9 private Integer id; 10 11 private String name; 12 13 public Integer getId() { 14 return id; 15 } 16 17 public void setId(Integer id) { 18 this.id = id; 19 } 20 21 public String getName() { 22 return name; 23 } 24 25 public void setName(String name) { 26 this.name = name; 27 } 28 29 @Override 30 public boolean equals(Object o) { 31 if(o instanceof StudentPK){ 32 StudentPK pk = (StudentPK)o; 33 if(this.id == pk.getId() && this.name.equals(pk.getName())){ 34 return true; 35 } 36 } 37 return false; 38 } 39 40 @Override 41 public int hashCode() { 42 return this.name.hashCode(); 43 } 44 45 }
Teacher
1 package com.bjsxt.hibernate; 2 3 import java.util.Date; 4 5 import javax.persistence.EmbeddedId; 6 import javax.persistence.Entity; 7 import javax.persistence.EnumType; 8 import javax.persistence.Enumerated; 9 import javax.persistence.GeneratedValue; 10 import javax.persistence.GenerationType; 11 import javax.persistence.Id; 12 import javax.persistence.IdClass; 13 import javax.persistence.SequenceGenerator; 14 import javax.persistence.Temporal; 15 import javax.persistence.TemporalType; 16 17 @javax.persistence.TableGenerator( 18 name="Teacher_GEN",//生成器名 19 table="GENERATOR_TABLE",//表名 20 pkColumnName = "pk_key",//第一个字段,key值 21 valueColumnName = "pk_value",//第二个字段,value值 22 pkColumnValue="Teacher",//记录值 23 allocationSize=1//增量 24 ) 25 26 @Entity 27 @SequenceGenerator(name="teacherSEQ",sequenceName="teacherSEQ_DB") 28 @IdClass(StudentPK.class) 29 public class Teacher { 30 private Integer id; 31 32 private String name; 33 34 private String title; 35 36 private Date birthday; 37 38 private ZhiCheng zhicheng; 39 40 @Id 41 public Integer getId() { 42 return id; 43 } 44 45 public void setId(Integer id) { 46 this.id = id; 47 } 48 49 @Id 50 public String getName() { 51 return name; 52 } 53 54 public void setName(String name) { 55 this.name = name; 56 } 57 58 public String getTitle() { 59 return title; 60 } 61 62 public void setTitle(String title) { 63 this.title = title; 64 } 65 66 @Temporal(TemporalType.DATE) 67 public Date getBirthday() { 68 return birthday; 69 } 70 71 public void setBirthday(Date birthday) { 72 this.birthday = birthday; 73 } 74 75 @Enumerated(value=EnumType.STRING) 76 public ZhiCheng getZhicheng() { 77 return zhicheng; 78 } 79 80 public void setZhicheng(ZhiCheng zhicheng) { 81 this.zhicheng = zhicheng; 82 } 83 84 }
链接: http://pan.baidu.com/s/1qYayZk4 密码: ta5c
所需jar包链接: http://pan.baidu.com/s/1hr35oVU 密码: yhsf