一、概述

  hibernate中使用两种方式实现主键生成策略,分别是XML生成id和注解方式(@GeneratedValue),下面逐一进行总结。

二、XML配置方法

  这种方式是在XX.hbm.xml文件中对generator进行配置,eg:

  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. <hibernate-mapping package="com.test.demo">
  6.  
  7. <class name="Student">
  8. <id name="id">
  9. <generator class="native"></generator>
  10. </id>
  11. <property name="name"></property>
  12. <property name="age"></property>
  13. </class>
  14. </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类型,取决于底层的数据库
  1. import javax.persistence.Entity;
  2. import javax.persistence.GeneratedValue;
  3. import javax.persistence.GenerationType;
  4. import javax.persistence.Id;
  5.  
  6. @Entity
  7. public class Person
  8. {
  9. private String name;
  10. private int age;
  11. private int id;
  12. public String getName()
  13. {
  14. return name;
  15. }
  16. public void setName(String name)
  17. {
  18. this.name = name;
  19. }
  20. public int getAge()
  21. {
  22. return age;
  23. }
  24. public void setAge(int age)
  25. {
  26. this.age = age;
  27. }
  28. @Id
  29. @GeneratedValue(strategy=GenerationType.AUTO)
  30. public int getId()
  31. {
  32. return id;
  33. }
  34. public void setId(int id)
  35. {
  36. this.id = id;
  37. }
  38. }
  • TABLE:使用表保存id值,即会为应用的表创建一张专门保存id的表
  1. import javax.persistence.Entity;
  2. import javax.persistence.GeneratedValue;
  3. import javax.persistence.GenerationType;
  4. import javax.persistence.Id;
  5. import javax.persistence.TableGenerator;
  6.  
  7. @Entity
  8. public class Person
  9. {
  10. private String name;
  11. private int age;
  12. private int id;
  13. public String getName()
  14. {
  15. return name;
  16. }
  17. public void setName(String name)
  18. {
  19. this.name = name;
  20. }
  21. public int getAge()
  22. {
  23. return age;
  24. }
  25. public void setAge(int age)
  26. {
  27. this.age = age;
  28. }
  29. @Id
  30. @TableGenerator(name="personID",table="personID_DB",pkColumnName="key_value",pkColumnValue="pk_value",valueColumnName="person",allocationSize=1)
  31. @GeneratedValue(strategy=GenerationType.TABLE,generator="personID")
  32. public int getId()
  33. {
  34. return id;
  35. }
  36. public void setId(int id)
  37. {
  38. this.id = id;
  39. }
  40. }
  • IDENTITY:identity column
  1. import javax.persistence.Entity;
  2. import javax.persistence.GeneratedValue;
  3. import javax.persistence.GenerationType;
  4. import javax.persistence.Id;
  5. import javax.persistence.TableGenerator;
  6.  
  7. @Entity
  8. public class Person
  9. {
  10. private String name;
  11. private int age;
  12. private int id;
  13. public String getName()
  14. {
  15. return name;
  16. }
  17. public void setName(String name)
  18. {
  19. this.name = name;
  20. }
  21. public int getAge()
  22. {
  23. return age;
  24. }
  25. public void setAge(int age)
  26. {
  27. this.age = age;
  28. }
  29. @Id
  30.  
  31. @GeneratedValue(strategy=GenerationType.IDENTITY)
  32. public int getId()
  33. {
  34. return id;
  35. }
  36. public void setId(int id)
  37. {
  38. this.id = id;
  39. }
  40. }
  • SEQUENCE:sequence

四、联合主键生成策略

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

  1. @Entity
  2. public class Person
  3. {
  4. //现在id和name组成联合主键
  5. private int id;
  6. private String name;
  7. private int age;
  8. ...
  9. }
  1. 首先将联合主键的属性提取出来,重新编写一个pojo类(原pojo类中的id,name要删除 并新加入属性“PersonPK”)
  2. 新建pojo类必须实现 java.io.Serializable 序列化接口
  3. 新pojo类要重写equals和hashCode方法
  1. public class PersonPK implements Serializable
  2. {
  3. private String name;
  4. private int id;
  5. public String getName()
  6. {
  7. return name;
  8. }
  9. public void setName(String name)
  10. {
  11. this.name = name;
  12. }
  13. public int getId()
  14. {
  15. return id;
  16. }
  17. public void setId(int id)
  18. {
  19. this.id = id;
  20. }
  21. @Override
  22. public int hashCode()
  23. {
  24. return this.name.hashCode();
  25. }
  26. @Override
  27. public boolean equals(Object obj)
  28. {
  29. if(obj instanceof PersonPK) {
  30. PersonPK pk = (PersonPK)obj;
  31. if(this.id == pk.getId() && this.name.equals(pk.getName())) {
  32. return true;
  33. }
  34. }
  35. return false;
  36.  
  37. }
  38. }

   联合主键生成策略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. <hibernate-mapping package="com.test.demo">
  6.  
  7. <class name="Person">
  8. <composite-id name="personPK" class="com.test.demo.PersonPK">
  9. <key-property name="id"></key-property>
  10. <key-property name="name"></key-property>
  11. </composite-id>
  12. <property name="age" />
  13. </class>
  14. </hibernate-mapping>

  联合主键ID生成策略的Annotation版本,共有三种方式,前三步骤一样,另外:

  方法1、在新类PersonPK前写@Embeddable,在原Person类的新属性PersonPK的get方法前写@id

  1. @Embeddable
  2. public class PersonPK implements Serializable
  3. {
  4. private static final long serialVersionUID = -7068850328521576106L;
  5. private String name;
  6. private int id;
  7. public String getName()
  8. {
  9. return name;
  10. }
  11. public void setName(String name)
  12. {
  13. this.name = name;
  14. }
  15. public int getId()
  16. {
  17. return id;
  18. }
  19. public void setId(int id)
  20. {
  21. this.id = id;
  22. }
  23. @Override
  24. public int hashCode()
  25. {
  26. return this.name.hashCode();
  27. }
  28. @Override
  29. public boolean equals(Object obj)
  30. {
  31. if(obj instanceof PersonPK) {
  32. PersonPK pk = (PersonPK)obj;
  33. if(this.id == pk.getId() && this.name.equals(pk.getName())) {
  34. return true;
  35. }
  36. }
  37. return false;
  38.  
  39. }
  40. }

  Person类中:

  1. @Entity
  2. public class Person
  3. {
  4. private PersonPK personPK;
  5. private int age;
  6.  
  7. public int getAge()
  8. {
  9. return age;
  10. }
  11. public void setAge(int age)
  12. {
  13. this.age = age;
  14. }
  15. @Id
  16. public PersonPK getPersonPK()
  17. {
  18. return personPK;
  19. }
  20. public void setPersonPK(PersonPK personPK)
  21. {
  22. this.personPK = personPK;
  23. }
  24. }

  方法2、新类无需添加注解,只需在原类Person新属性PersonPK的get方法前写@EmbeddID即可

  1. @Entity
  2. public class Person
  3. {
  4. private PersonPK personPK;
  5. private int age;
  6.  
  7. public int getAge()
  8. {
  9. return age;
  10. }
  11. public void setAge(int age)
  12. {
  13. this.age = age;
  14. }
  15. @EmbeddedId
  16. public PersonPK getPersonPK()
  17. {
  18. return personPK;
  19. }
  20. public void setPersonPK(PersonPK personPK)
  21. {
  22. this.personPK = personPK;
  23. }
  24. }

  方法3、新pojo类无需加注解,原pojo类的id,name属性保留不变,也无需新增“TercherPK”属性。 只在id,name的get方法前都加@Id,并在原pojo类前加@IdClass(PersonPK.class):

  原类Person:

  1. @Entity
  2. @IdClass(PersonPK.class)
  3. public class Person
  4. {
  5. private int age;
  6. private String name;
  7. private int id;
  8. @Id
  9. public String getName()
  10. {
  11. return name;
  12. }
  13. public void setName(String name)
  14. {
  15. this.name = name;
  16. }
  17. @Id
  18. public int getId()
  19. {
  20. return id;
  21. }
  22. public void setId(int id)
  23. {
  24. this.id = id;
  25. }
  26. public int getAge()
  27. {
  28. return age;
  29. }
  30. public void setAge(int age)
  31. {
  32. this.age = age;
  33. }
  34. }

  运行测试程序(针对上述三种方法,测试用例需要稍作修改,这里不在赘述):

  1. public class PersonTest
  2. {
  3. private static SessionFactory sf=null;
  4. @BeforeClass
  5. public static void beforeClass()
  6. {
  7. sf=new AnnotationConfiguration().configure().buildSessionFactory();
  8. }
  9. @Test
  10. public void test()
  11. {
  12. PersonPK personPK=new PersonPK();
  13. personPK.setId(1);
  14. personPK.setName("xujian");
  15. Person p=new Person();
  16. p.setAge(23);
  17. p.setPersonPK(personPK);
  18. Session session=sf.openSession();
  19. session.beginTransaction();
  20. session.save(p);
  21. //提交事物
  22. session.getTransaction().commit();
  23. session.close();
  24. sf.close();
  25. }
  26. @AfterClass
  27. public static void afterClass()
  28. {
  29. sf.close();
  30. }
  31. }

  可以看到:

  生成的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. SAP 以工序为基准进行发料 机加工行业 Goods Issue to Routing

    SAP 以工序为基准进行发料   这个流程是在业务有关需求,业务需要按照工序发料,一个工单有多个工序,而料是要发到每个工序上,而且没到工序之间在物理上是有距离的,所以仓管员在打印配发单之后希望了解到哪 ...

  2. e777. 获得JList组件的所有项

    // Create a list String[] items = {"A", "B", "C", "D"}; JLis ...

  3. CI框架 -- 密码哈希

    哈希算法是一个单向函数.它可以将任何大小的数据转化为定长的“指纹”,并且无法被反向计算 依赖性 crypt() 函数需支持 CRYPT_BLOWFISH 常量 PASSWORD_BCRYPT PASS ...

  4. C# 获取web.config配置文件

    .ConfigurationManager提供对客户端应用程序配置文件的访问. 其有两个属性1.ConnectionStrings 获取当前应用程序默认配置的 ConnectionStringsSec ...

  5. Drools 语法

    Drools 语法 规则语法 package: package 的名字是随意的,不必必须对应物理路径 import: 导入外部变量 规则的编译与运行要通过Drools 提供的各种API 来实现.API ...

  6. Material Design Support 8大控件介绍

    TextInputLayout 显示提示信息 能够通过调用setError()在EditText以下显示一条错误信息 FloatingActionButton 悬浮操作按钮 Snackbar 相当于底 ...

  7. php public,static,private,protected,final,const,abstract

    public:权限是最大的,可以内部调用,实例调用等. protected: 受保护类型,用于本类和继承类调用. private: 私有类型,只有在本类中使用. final:PHP 5:不被改,不被继 ...

  8. [转]jmeter 自定义测试脚本

    http://blog.csdn.net/kash_chen007/article/details/37690411 http://wangym.iteye.com/blog/731729 1.创建一 ...

  9. 在window的cmd窗口下运行linux命令

    之前看很多视频老师都是用Linux命令操作命令框,感觉很方便,自己在cmd窗口试了一下,所有这些命令都提示不是内部或外部命令,后来发现了windows还有一个powershell命令行工具,用起来似乎 ...

  10. QT编译错误: multiple definition of `qMain(int, char**)'

    QT使用过程中来回添加修改代码,结果出现了编译错误:error: multiple definition of `qMain(int, char**)' 一直看我的源文件是都哪里有错误,最后发现是在p ...