Hibernate系列之Id生成策略

来源:互联网 发布:计划表软件 编辑:程序博客网 时间:2024/04/29 10:52

一、概述

  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类型,取决于底层的数据库
 View Code
  • TABLE:使用表保存id值,即会为应用的表创建一张专门保存id的表
 View Code
  • IDENTITY:identity column
 View Code
  • SEQUENCE:sequence

四、联合主键生成策略

  有的时候我们需要将一个实体的2个或多个字段联合起来作为主键,就是说,不能有2个或多个对象的这几个字段值都相同的情况发生。现在我们要将Person字段的id和name字段联合作为主键:

复制代码
@Entitypublic 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

复制代码
@Embeddablepublic 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类中:

复制代码
@Entitypublic 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即可

复制代码
@Entitypublic 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组成联合主键

  

0 0