`

hibernate的id生成策略

 
阅读更多
查看文章
   
2011-09-27 17:40
Hibernate的id生成策略有下面几种:
1.Increment

用于为long,short或者int类型生成唯一标识,只有在没有其他进程往同一张表中插入数据库时才能使用。在集群下不要使用。

对于集群为什么不要使用,是因为在一个大型的项目中如果我们有很多的服务器为项目提供服务,这样就会出项一种情况,A服务在15:25拿到数据库中的数据的 id为15,此时B服务器向数据库中插入了一条数据,这时数据库中的id为16了,但A服务中的session依旧保存着15,但下一条数据通过A服务向数据库中保存数据的时候session会为id赋值为16,可数据库中的id已经为16了,所以这时保存就会出错。


2.identity:

对 DB2,MySQL,MS SQL Server,Sybase 和 HypersonicSQL 的内置标识字段提供支持。返回的标识符是 long,short 或者 int 类型的。


3.sequence

在 DB2,PostgreSQL,Oracle,SAP DB,McKoi 中使用序列(sequence), 而在 Interbase

中使用生成器(generator)。返回的标识符是 long,short 或者 int 类型的。


4.hilo

使用一个高/低位算法高效的生成 long,short 或者 int 类型的标识符。给定一个表和字段(默认分别是 hibernate_unique_key 和 next_hi)作为高位值的来源。高/低位算法生成的标识符只在一个特定的数据库中是唯一的。


5.seqhilo

使用一个高/低位算法来高效的生成 long,short 或者 int 类型的标识符,给定一个数据库序列(sequence)的名字。


6.uuid

基于一个自定义的算法生成一个128位的UUID。所产生的价值
表示为32个十六进制数字的字符串。


7.guid

在 MS SQL Server 和 MySQL 中使用数据库生成的 GUID 字符串。


8.native

根据底层数据库的能力选择 identity、sequence 或者 hilo 中的一个。


9.assigned

让应用程序在调用 save() 之前为对象分配一个标识符。这是 <generator> 元素没有指定时的默认生成策略。


10.select

通过数据库触发器选择一些唯一主键的行并返回主键值来分配一个主键。


11.foreign

使用另外一个相关联的对象的标识符。它通常和 <one-to-one> 联合起来使用。


12.sequence-identity

一种特别的序列生成策略,它使用数据库序列来生成实际值,但将它和 JDBC3 的getGeneratedKeys 结合在一起,使得在插入语句执行的时候就返回生成的值。目前为止只有面向 JDK 1.4 的 Oracle 10g 驱动支持这一策略。由于 Oracle 驱动程序的一个 bug,这些插入语句的注释被关闭了。

我们通常用的比较多的就是native、identity、sequence在一些情况下我们会用到uuid,其他的就用的很少了。


举例说明uuid

下面来测试一下uuid,还用原来的Student类,既然是测试uuid那我们的id就必须为String类型了。


Student类

package cc.tukai.entity;

import java.io.Serializable;

import javax.persistence.Entity;

import javax.persistence.Id;

import javax.persistence.Table;

//@Entity

//@Table(name = "Student")

public class Student implements Serializable {

         private static final long serialVersionUID = -5596241291862147220L;

         private String id;

         private String name;

         private int age;

         //@Id

         public String getId() {

                   return id;

         }

         public void setId(String id) {

                   this.id = 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;

         }


Student.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="cc.tukai.entity">

         <class name="Student" table="student">

                   <id name="id" column="id">

                            <generator class="uuid"></generator>

                   </id>

                   <property name="name" type="java.lang.String">

                            <column name="name" length="32"></column>

                   </property>

                   <property name="age" type="java.lang.Integer">

                            <column name="age" length="10"></column>

                   </property>

         </class>

</hibernate-mapping>


hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC

"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

         <session-factory>

                   <!-- Database connection settings -->

                   <property name="connection.driver_class">com.mysql.jdbc.Driver</property>

                   <property name="connection.url">jdbc:mysql://127.0.0.1/hibernate</property>

                   <property name="connection.username">root</property>

                   <property name="connection.password">1234</property>

                   <!-- SQL dialect -->

                   <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

                   <!-- Echo all executed SQL to stdout -->

                   <property name="show_sql">true</property>

                   <!-- Drop and re-create the database schema on startup -->

                   <property name="hbm2ddl.auto">create</property>

                   <!-- <mapping class="cc.tukai.entity.Student"/> -->

                   <mapping resource="cc/tukai/entity/Student.hbm.xml"/>

         </session-factory>

</hibernate-configuration>


测试类Test

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

import cc.tukai.entity.Student;

public class Test {

         @org.junit.Test

         public void testSave() {

                   Student student = new Student();

                   student.setAge(20);

                   student.setName("test");

                   SessionFactory factory = new Configuration().configure()

                                     .buildSessionFactory();

                   Session session = factory.openSession();

                   session.beginTransaction();

                   session.save(student);

                   session.getTransaction().commit();

                   session.close();

                   factory.close();

         }

运行一下我们的测试类,查看一下数据库

hibernate5_id生成策略

由上图我们可以看到hibernate已经为我们创建了student表,并且主键id为varchar(255)类型,生成的值也是一个字符串。


举例说明native

现在我们将生成策略改为native,那就要将原来的Student.hbm.xml中的    <generator class="uuid"></generator>改为         <generator class="native"></generator>

由于对于mysql而言,native是根据 auto_increment来生成主键的值的,所以要将实体类的id从刚刚的String类型改为int类型。好的,改完之后将原来数据库中的 Student表删除掉,因为hibernate识别不了类型改变,所以他不会帮你重新建表。这个时候就可以重新运行我们原来的测试类了。

下面为测试类运行完产生的结果:

hibernate5_id生成策略

下面我们用Annotation来操作一下上面的例子
对于jpa有四种id生成策略:

1.默认为auto

I.对于mysql而言为auto_increment

II.对于oracle而言为sequence

2.identity

3.sequence

4.table

现在我们更改一下上面例子中的代码

Student类

package cc.tukai.entity;

import java.io.Serializable;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.Table;

@Entity

@Table(name = "Student")

public class Student implements Serializable {

         private static final long serialVersionUID = -5596241291862147220L;

         private int id;

         private String name;

         private int age;

         @Id

         @GeneratedValue(strategy = GenerationType.AUTO)

         public int getId() {

                   return id;

         }

         public void setId(int id) {

                   this.id = 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;

         }

hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>

<!DOCTYPE hibernate-configuration PUBLIC

"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

         <session-factory>

                   <!-- Database connection settings -->

                   <property name="connection.driver_class">com.mysql.jdbc.Driver</property>

                   <property name="connection.url">jdbc:mysql://127.0.0.1/hibernate</property>

                   <property name="connection.username">root</property>

                   <property name="connection.password">1234</property>

                   <!-- SQL dialect -->

                   <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

                   <!-- Echo all executed SQL to stdout -->

                   <property name="show_sql">true</property>

                   <!-- Drop and re-create the database schema on startup -->

                   <property name="hbm2ddl.auto">create</property>

                   <mapping class="cc.tukai.entity.Student" />

                  <!--<mapping resource="cc/tukai/entity/Student.hbm.xml"/> -->

         </session-factory>

</hibernate-configuration>

测试类Test

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

import cc.tukai.entity.Student;

public class Test {

         @org.junit.Test

         public void testSave() {

                   Student student = new Student();

                   student.setAge(20);

                   student.setName("test");

                   SessionFactory factory = new Configuration().configure()

                                     .buildSessionFactory();

                   Session session = factory.openSession();

                   session.beginTransaction();

                   session.save(student);

                   session.getTransaction().commit();

                   session.close();

                   factory.close();

         }

运行完后的结果:

hibernate5_id生成策略

注:

对于oracle而言,hibernate默认会为我们创建一个sequence,然而默认每张表用的都是这一个sequence。这里补充一下指定sequence的方法。

首先要在类的前面添加

@SequenceGenerator(name = "生成器的名字",sequenceName=”数据库中sequence的名字")

在@GeneratedValue的中添加generator="生成器的名字"

hibernate5_id生成策略

table生成策略

如果你想将你的程序能够真正意义上的跨数据库平台,那hibernate为我们提供了一种id的生成策略――Table,当然这种情况是很少用的,毕竟现在写程序一般是不会要求我们跨数据库平台的。

下面我们就这种策略来说明一下他的配置:

在类的前面添加

@javax.persistence.TableGenerator(

name="生成器的名称",

table="数据库表名",

pkColumnName = "表的字段名",

valueColumnName = "表的值名称"

pkColumnValue="字段的值",

allocationSize=每次的步长

在id的get方法前添加

@GeneratedValue(strategy = GenerationType.TABLE,generator="生成器的名字")

对于Table这种id生成器策略的意思是通过表来获取id的值,首先他会将预定的值保存到数据库中,默认为1,举个例子说明一下吧:如果我定义 tableGenerator的数据库表名为Student_generator,pkColumnName为 PK_Key,valueColumnName为PK_Value,pkColumnValue为Student,allocationSize为1,这个时候hibernate会先建一张Student_generator表,这张表有两个字段,一个是类型为varchar(255),字段名为 PK_Key,一个是类型为int(11),字段名为PK_Value,首先会插入一个值为(Student,1),但我们插入数据时,而这个数据的id 生成策略为上面的这个策略,那hibernate首先会执行:select PK_Value from student_generator where PK_Key这条语句,然后取出这个值作为id的值,之后将PK_Value的值改为原来的值加上步长,这个新产生的值作为下一个需要这个id的值。这中方式可以跨任何的数据库,并且一个数据库表可以保存所有的表中要用到的id。

  
联合主键

一般我们设计数据库的时候尽量不要使用联合主键,但怕的就是我们现在接手的是一个遗留的项目,人家设计的时候就是用的联合主键,遇到这样的项目那我们怎样用hibernate去映射这个联合主键呢?

如上面中我们经常说到的Student类,假如现在我们要将原来的id和name做为联合主键,那该怎么配置呢?

作为面向对象的设计,这样的情况我们一般会新建一个类作为主键类,也就是我们要新建一个类,比如说Student_PK,里面有id和name这两个属性。当然这个类我们要重写他的equals,hashcode方法,以及要去实现java.io.Serializable接口。为什么要去重写这些方法,主要是因为他是主键我们必须要让他唯一,为什么要实现java.io.Serializable接口,是因为在项目中可能会出现内存不够的情况,那这样的话就要将内存里面的对象写到硬盘中,所以就必须要实现这个接口。

这样我们将主键作为了一个类,那我们本来的Student类中就不要有id和name属性了,那就用主键类来代替了。

Student.java

package cc.tukai.entity;

import java.io.Serializable;

import javax.persistence.Entity;

import javax.persistence.Table;

@Entity

@Table(name = "Student")

public class Student implements Serializable {

    private static final long serialVersionUID = -5596241291862147220L;

    private Student_PK pk;

    private int age;

    public Student_PK getPk() {

       return pk;

    }

    public void setPk(Student_PK pk) {

       this.pk = pk;

    }

    public int getAge() {

       return age;

    }

    public void setAge(int age) {

       this.age = age;

    }

Student_PK

package cc.tukai.entity;

import java.io.Serializable;

public class Student_PK implements Serializable {

    private static final long serialVersionUID = 1334477470452734661L;

    private int id;

    private String name;

    public int getId() {

       return id;

    }

    public void setId(int id) {

       this.id = id;

    }

    public String getName() {

       return name;

    }

    public void setName(String name) {

       this.name = name;

    }

    @Override

    public int hashCode() {

       final int prime = 31;

       int result = 1;

       result = prime * result + id;

       result = prime * result + ((name == null) ? 0 : name.hashCode());

       return result;

    }

    @Override

    public boolean equals(Object obj) {

       if (this == obj)

           return true;

       if (obj == null)

           return false;

       if (getClass() != obj.getClass())

           return false;

       Student_PK other = (Student_PK) obj;

       if (id != other.id)

           return false;

       if (name == null) {

           if (other.name != null)

              return false;

       } else if (!name.equals(other.name))

           return false;

       return true;

    }

Student.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="cc.tukai.entity">

    <class name="Student" table="student">

       <composite-id name="pk" class="Student_PK">

           <key-property name="id"></key-property>

           <key-property name="name"></key-property>

       </composite-id>

       <property name="age" type="java.lang.Integer">

           <column name="age" length="10"></column>

       </property>

    </class>

</hibernate-mapping>

Test.java

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

import cc.tukai.entity.Student;

import cc.tukai.entity.Student_PK;

public class Test {

         @org.junit.Test

         public void testSave() {

                   Student_PK pk=new Student_PK();

                   pk.setName("test");

                   pk.setId(1);

                   Student student = new Student();

                   student.setAge(20);

                   student.setPk(pk);

                   SessionFactory factory = new Configuration().configure()

                                     .buildSessionFactory();

                   Session session = factory.openSession();

                   session.beginTransaction();

                   session.save(student);

                   session.getTransaction().commit();

                   session.close();

                   factory.close();

         }

运行完测试类之后的结果:

hibernate5_id生成策略

由上图就可以看出id和name都为主键了。

用Annotation的方法配置联合主键

用Annotation的方法配置联合主键,管方提供了三种方法。

1.将组件类注解为@Embeddable,并将组件的属性注解为@Id

就是将Student_PK这个类注解为@Embeddable,并且将Student的getPK方法注解为@Id

2.将组件的属性注解为@EmbeddableId">2.将组件的属性注解为@EmbeddableId

在Student的getPK方法注解为@EmbeddableId

3.将类注解为@IdClass,并将该实体中所有属于主键的属性都注解为@Id

将 Student类中依旧添加id和name这两个属性,并且将这两个属性的get方法都注解为@Id,然后在Student类中添加 @IdClass(Student_PK.class)">然后在Student类中添加@IdClass(Student_PK.class)。


分享到:
评论

相关推荐

    Hibernate教程02_ID生成策略

    在Java的持久化框架Hibernate中,ID生成策略是至关重要的一个环节。它是用来唯一标识数据库中每一行记录的关键部分。本教程将详细讲解Hibernate中的ID生成策略,以及如何在实际项目中灵活应用。 首先,ID生成策略是...

    常用Hibernate主键生成策略

    ### 常用Hibernate主键生成策略详解 #### 一、引言 在数据库设计与操作过程中,主键是确保数据唯一性的关键要素之一。在实际应用中,开发者经常需要处理不同类型的数据库,并且需要应对各种不同的主键生成需求。...

    Hibernate中主键生成策略

    在Java的持久化框架Hibernate中,主键生成策略是一个至关重要的概念,它决定了数据库表中主键值如何自动生成。主键通常是表中唯一标识记录的一列,对于数据的完整性和一致性至关重要。以下是对Hibernate中主键生成...

    Hibernate各种主键生成策略与配置详解

    ### Hibernate 主键生成策略与配置详解 #### 一、概述 在使用Hibernate进行持久化操作时,合理选择和配置主键生成策略对于确保数据的一致性和优化性能至关重要。本文将详细介绍几种常见的主键生成策略,并结合示例...

    hibernate主键生成策略详解

    ### hibernate主键生成策略详解 #### 一、assigned **assigned** 主键生成策略意味着主键的值是由外部程序负责生成的,并且在执行 `save()` 方法之前必须明确指定一个值。在这种策略下,Hibernate 不参与主键的...

    hibernate 主键生成策略

    ### Hibernate 主键生成策略详解 Hibernate 是一款流行的 Java 持久层框架,它提供了对象关系映射(ORM)的功能,使得 Java 开发者能够更高效地与数据库进行交互。在 Hibernate 中,主键生成策略是一项核心功能,...

    hibernate映射主键生成策略native

    ### Hibernate映射主键生成策略native #### 一、引言 在ORM(对象关系映射)技术中,Hibernate作为一款流行的Java持久层框架,在处理数据持久化方面提供了丰富的功能和灵活性。其中,主键生成策略是Hibernate配置...

    JAVA 的ID生成策略

    JAVA ID生成策略是一种在Hibernate框架中使用的策略,用于生成实体类的主键值。这种策略在Annotation情况下,主要有三种方式生成主键值。 第一种方式是使用数据库的自动增长字段生成。这种方式使用@GeneratedValue...

    hibernate主键生成策略

    ### Hibernate 主键生成策略 在Hibernate框架中,主键生成策略是对象持久化的重要组成部分,它主要用于自动管理和生成实体类的唯一标识(即主键)。根据给定的文件信息,我们可以详细探讨这几种主键生成策略的特点...

    Hibernate主键生成策略.docx

    ### Hibernate 主键生成策略详解 #### 一、概述 Hibernate 是一种流行的 Java 持久化框架,它简化了数据库操作,并提供了多种主键生成策略。主键是表中的一个或多个字段组合,用于唯一标识表中的每一条记录。...

    ID生成策略

    ### ID生成策略详解 在软件开发中,尤其是数据库应用领域,如何高效且合理地生成唯一标识符(ID)是至关重要的。本文将详细介绍几种常见的ID生成策略:`sequence`、`native`、`identity`、`foreign`等,并探讨它们...

    Java探索之Hibernate主键生成策略详细介绍

    Hibernate主键生成策略详细介绍 在Java探索中,Hibernate提供了多种主键生成策略,满足不同场景下的需求。下面是对Hibernate主键生成策略的详细介绍: 1. Increment主键生成策略 Increment主键生成策略是由...

    Hibernate的主键生成策略

    ### Hibernate的主键生成策略详解 #### 一、概述 在使用Hibernate进行持久化操作时,主键生成策略的选择对于数据库性能及应用架构至关重要。本文将详细介绍Hibernate中五种常用的主键生成策略:assigned、...

    hibernate生成实体类

    - 在“ID Generator”选项中,可以选择不同的ID生成策略,例如“native”表示由底层数据库自动生成主键值。 - 完成后点击“Next”按钮继续。 7. **配置逆向工程细节:** 进入“Configure reverse engineering ...

    如何使用Hibernate Tools生成Entity Bean

    在设置中,你可以选择生成Bean的命名策略、访问类型(字段访问或属性访问)、生成的类的包名和类名等。 4. **查看并使用生成的Entity Bean** Hibernate Tools会自动生成一个对应的Java类,比如`User.java`。这个类...

    Hibernate自动生成表demo

    在本教程中,我们将探讨如何利用Hibernate的注解功能,通过实体类自动生成数据库中的表。这极大地简化了数据库建模过程,同时也减少了手动编写SQL语句的工作量。 首先,我们需要理解Hibernate的核心概念。ORM框架如...

Global site tag (gtag.js) - Google Analytics