Hibernate ID生成策略/联合主键解决方案

对于不同数据库的主键id,生成是不一样的.Hibernate中也有相对应的策略.

 

可选的<generator>子元素是一个Java类的名字, 用来为该持久化类的实例生成唯一的标识。如果这个生成器实例需要某些配置值或者初始化参数, <param>元素来传递

所有的生成器都实现org.hibernate.id.IdentifierGenerator接口。

 

下面是一些内置生成器的快捷名字:

increment

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

identity

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

sequence

DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence) 而在Interbase中使用生成器(generator)。返回的标识符是long, short或者 int类型的。

hilo

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

seqhilo

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

uuid

用一个128-bitUUID算法生成字符串类型的标识符, 这在一个网络中是唯一的(使用了IP地址)。UUID被编码为一个3216进制数字的字符串。

guid

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

native

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

assigned

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

select

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

foreign

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

sequence-identity

一种特别的序列生成策略,使用数据库序列来生成实际值,但将它和JDBC3getGeneratedKeys结合在一起,使得在插入语句执行的时候就返回生成的值。目前为止只有面向JDK 1.4Oracle 10g驱动支持这一策略。注意,因为Oracle驱动程序的一个bug,这些插入语句的注释被关闭了。(原文:Note comments on these insert statements are disabled due to a bug in the Oracle drivers.

 

XML配置方法:

<hibernate-mapping>

    <class name="com.hibernate.test.entitys.Student" table="student">

       <id name="id">

           <!--<generator class="assigned"/>-->

           <generator class="native"/><!—从指定使用哪种id生成策略-->

       </id>

    <property name="name"/>

    <property name="sex"/>

    <property name="password"/>

    </class>

   

</hibernate-mapping>

 

 

 

 

Annotation注解方法:

1.

//映射到数据库中的主键

    @Id

//此注解默认值为auto,也就是为自动.相当于在配置文件中使用”native”

    @GeneratedValue

    public int getId() {

       return id;

    }

2.

如果想指定具体的id生成策略(IDENTITY/SEQUENCE/AUTO),比方说为oracle数据库指定id生成策略,那么就只能用sequence.

//只需要把注解写成这样就行(也就是指定策略为自己需要的类型,GenerationType是各种策略的枚举值)

@GeneratedValue(strategy=GenerationType.SEQUENCE)

 

上述方法虽然可行,但是会有点别扭,哪里别扭呢?

也就是生成表的时候,所有的表都使用同一个sequence.虽然也不碍事,但毕竟不符合习惯,我们的习惯应该是每张表都有它自己的sequence.

用下面的方法就可以解决:

 

 

 

//映射成数据库中的表

@Entity

//如果类名和数据库中的表名不一致,通过此注解声明

@Table(name="_Teacher")

//为每张表指定自己的sequence,name属性是生成器的名字,sequenceName是数据库中sequence的名字

@SequenceGenerator(name="TeacherSEQ",sequenceName="TeacherSEQ_DB")

public class Teacher {

    private int id;

    private String name;

    private String title;

    private String myRealName;

    private ZhiCheng zhiCheng//自定义枚举类型

   

    //如果不需要将此属性映射到数据库中的字段,用此注解

    @Transient

    public String getMyRealName() {

       return myRealName;

    }

    public void setMyRealName(String myRealName) {

       this.myRealName = myRealName;

    }

 

    //映射到数据库中的主键

    @Id

    //注意这里的第二个参数,值是在类上指定的生成器的名字!

   @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="TeacherSEQ")

    public int getId() {

       return id;

    }

    public void setId(int id) {

       this.id = id;

    }

 

    //如果属性名和数据库中的字段不一样,通过此注解声明

    @Column(name="_name")

    public String getName() {

       return name;

    }

    public void setName(String name) {

       this.name = name;

    }

 

    public String getTitle() {

       return title;

    }

    public void setTitle(String title) {

       this.title = title;

    }

   

    //映射自定义枚举(映射到数据库中为Varchar类型)

    @Enumerated(EnumType.STRING)

    public ZhiCheng getZhiCheng() {

       return zhiCheng;

    }

    public void setZhiCheng(ZhiCheng zhiCheng) {

       this.zhiCheng = zhiCheng;

    }

}

 

 

 

 

 

联合主键的映射:

首先要把联合主键的几个属性提取为一个主键类;

 

1.XML配置

         composite-id

         <!—-指定提取出来的联合主键的类-->

<composite-id name="pk" class="com.hibernate.test.entitys.TeacherPK">

       <key-property name="id"/><!—-指定联合主键的各个属性-->

       <key-property name="name"/>

    </composite-id>

需要重写联合主键类的hashcode()equals()

hashcode()只需要返回其中一个String类型的hashcode就行

equals()需要判断联合主键类的各个属性都相同,才能返回true,反之.

 

 

2.Annotation联合主键映射的三种方法:

 

Method 1:给提取出来的主键类加上@Embeddable注解,实体类getXXX主键的方法上加@Id

 

Method 2:提取出来的主键类不加注解,实体类getXXX主键的方法上加@EmbeddedId.    (以验证通过)

 

Method 3:提取出来的主键类不加注解,实体类的联合主键分别都加@Id,实体类上加@IdClass(这里指定主键类)

 

 

 

eg:

 

//映射成数据库中的表

@Entity

@IdClass(TeacherPK.class)---第三种方法

public class Teacher implements Serializable {

    /*private int id;

    private String name;  把这个类中的idname属性提取为联合主键*/

    private String title;

    private TeacherPK pk;

   

    @Id---第一种方法

    @EmbeddedId---第二种方法

    getPk(){…}

    setPk(){…}

   

 

第三种方法去掉主键类对象,

@Id

getId(){…}

@Id

getName(){…}

    public String getTitle() {

       return title;

    }                               

    public void setTitle(String title) {

       this.title = title;

    }

}

 

/**

 * 提取出来的主键类

 * @author PF_CQ

 *

 */

@Embeddable----第一种方法

第二种方法,去掉注解

第三种方法,去掉注解

public class TeacherPK implements Serializable {

  private static final long serialVersionUID = -6247050545165388561L;

  private int id;

  private String name;

 

  getXXX{}…setXXX{}

  getXXX{}…setXXX{}

 

  重写hashcode 和 equals 方法

 

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值