一、概述

  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;
...
}
  1. 首先将联合主键的属性提取出来,重新编写一个pojo类(原pojo类中的id,name要删除 并新加入属性“PersonPK”)
  2. 新建pojo类必须实现 java.io.Serializable 序列化接口
  3. 新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组成联合主键

  

  

  

  

  

  

Hibernate系列之ID生成策略的更多相关文章

  1. 图解Janusgraph系列-分布式id生成策略分析

    JanusGraph - 分布式id的生成策略 大家好,我是洋仔,JanusGraph图解系列文章,实时更新~ 本次更新时间:2020-9-1 文章为作者跟踪源码和查看官方文档整理,如有任何问题,请联 ...

  2. Hibernate 再接触 ID生成策略

    Xml 方法 在student.hbm.xml中 <generator class="uuid"></generator> 取值如下 1.identity: ...

  3. hibernate(四)ID生成策略

    一.ID生成策略配置 1.ID生成方式在xml中配置方式: <?xml version="1.0"?> <!DOCTYPE hibernate-mapping P ...

  4. hibernate 中id生成策略

    数据库的设计和操作中,我们通常会给表建立主键. 主键,可以分为自然主键和代理主键. 自然主键表示:采用具有业务逻辑含义的字段作为表的主键.比如在用户信息表中,采用用户的身份证号码作为主键.但是这样一来 ...

  5. Rhythmk 学习 Hibernate 03 - Hibernate 之 延时加载 以及 ID 生成策略

    Hibernate 加载数据 有get,跟Load 1.懒加载: 使用session.load(type,id)获取对象,并不读取数据库,只有在使用返回对象值才正真去查询数据库. @Test publ ...

  6. [Hibernate开发之路](4)ID生成策略

    一 对象关系数据库映射之Id 被映射的类必须定义相应数据库表主键字段.大多数类有一个JavaBeans风格的属性, 为每个实例包括唯一的标识. <id> 元素定义了该属性到数据库表主键字段 ...

  7. hibernate ID生成策略配置

    1.Student.hbm.xml配置 <hibernate-mapping package="com.wxh.hibernate.model"> <class ...

  8. hibernate注解主键生成策略

    Id生成策略: @GeneratedValue,JPA通用策略生成器 . JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO.  TABLE:使用一个特定的数据库表格来 ...

  9. JPA ID生成策略(转---)

    尊重原创:http://tendyming.iteye.com/blog/2024985 JPA ID生成策略 @Table Table用来定义entity主表的name,catalog,schema ...

随机推荐

  1. 贝塞尔曲线.简单推导与用opengl实现动态画出。

    在opengl中,我们可以用少许的参数来描述一个曲线,其中贝塞尔曲线算是一种很常见的曲线控制方法,我们先来看维基百科里对贝塞尔曲线的说明: 线性贝塞尔曲线 给定点P0.P1,线性贝塞尔曲线只是一条两点 ...

  2. static为什么一般与final一起用?

    static和final的意义是不同的,static修饰的时候代表对象是静态的,而final修饰的时候代表对象只能赋值一次,他们连用的时候是因为定义的那个对象既要它是静态的,也要求它的值不能再被修改. ...

  3. (诊断)解决GitHub使用双因子身份认证“Two-Factor Athentication”后无法git push 代码的“fatal: Authentication failed for ...”错误

    在GitHub上采取双因子身份认证后,在git push 的时候将会要求填写用户的用户名和密码,用户名就是用户在GitHub上申请的用户名,但是密码不是普通登录GitHub的密码. 一旦采取双因子身份 ...

  4. Java设计模式之五大创建型模式(附实例和详解)

    一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥 ...

  5. 写一个方法,用一个for循环打印九九乘法表

    public class MultiplicationTable { /**  * @description 写一个方法,用一个for循环打印九九乘法表   * @author  wangkun  * ...

  6. 设置wetty不需要账号登录便可进行命令行操作

    前一篇随笔我们将了Linux怎么安装部署Wetty服务,但是我们看到,在浏览器中输入http://127.0.0.1:3000进行访问的时候,还需要我们输入账号密码进行认证(如下图第一行所示). 但在 ...

  7. 周期性调度器scheduler_tick

    周期性调度器由中断实现,系统定时产生一个中断,然后启动周期性调度器,周期性调度器执行过程中要关闭中断, 周期性调度器执行完毕后再打开中断(handle_IRQ_event,  IRQF_DISABLE ...

  8. 实现一个div,左边固定div宽度200px,右边div自适应

    实现一个div,左边固定div宽度200px,右边div自适应<div class= "container"> <div class="left&quo ...

  9. 系统安装SQL Sever2000后1433端口未开放,如何打开1433端口的解决方法

    这篇文章主要针对Win2003系统安装SQL Sever2000后1433端口未开放,如何打开1433端口的解决方法. 用了几年的Windows2003和SQL Server2000了,不过这个问题倒 ...

  10. Vim 操作符命令和动作命令

    http://www.cnblogs.com/littlerabbit/articles/2349951.html