Hibernate的主键生成策略有好几种:
1) assigned
2) hilo
3) seqhilo
4) increment
5) identity
6) sequence
7) native
8) uuid.hex
9) uuid.string
10) foreign
一般而言,利用uuid.hex方式生成主键将提供最好的性能和数据库平台适
应性。另外由于常用的数据库,如Oracle、DB2、SQLServer、MySql 等,都提
供了易用的主键生成机制(Auto-Increase 字段或者Sequence)。我们可以在数
据库提供的主键生成机制上,采用generator-class=native的主键生成方式。
不过值得注意的是,一些数据库提供的主键生成机制在效率上未必最佳,
大量并发insert数据时可能会引起表之间的互锁。
数据库提供的主键生成机制,往往是通过在一个内部表中保存当前主键状
态(如对于自增型主键而言,此内部表中就维护着当前的最大值和递增量),
之后每次插入数据会读取这个最大值,然后加上递增量作为新记录的主键,之
后再把这个新的最大值更新回内部表中,这样,一次Insert操作可能导致数据
库内部多次表读写操作,同时伴随的还有数据的加锁解锁操作,这对性能产生
了较大影响。
因此,对于并发Insert要求较高的系统,推荐采用uuid.hex 作为主键生成
机制。
另外我们可以扩展Hibernate的类来做自己的主键生成策略:
java 代码
- package com.gsta.eshore.framework.util.uid;
- import java.io.Serializable;
- import org.hibernate.engine.SessionImplementor;
- import org.hibernate.id.AbstractUUIDGenerator;
- import org.hibernate.id.Configurable;
- import org.hibernate.id.IdentifierGenerator;
- import java.util.Properties;
- import org.hibernate.Hibernate;
- import org.hibernate.dialect.Dialect;
- import org.hibernate.type.Type;
- import org.hibernate.util.PropertiesHelper;
-
-
-
-
- public class UIDGenerator extends AbstractUUIDGenerator implements Configurable {
- private static long lastTime = System.currentTimeMillis();
- private static short lastCount = -32768;
- private static Object mutex = new Object();
- private static long ONE_SECOND = 1000L;
- private String sep = "";
- public Serializable generate(SessionImplementor session, Object obj) {
- long l = 0L;
- short word0 = 0;
- int i = 0;
- synchronized(mutex)
- {
- if(lastCount == 32767)
- {
- for(boolean flag = false; !flag;)
- {
- l = System.currentTimeMillis();
- if(l < lastTime + ONE_SECOND)
- {
- try
- {
- Thread.currentThread();
- Thread.sleep(ONE_SECOND);
- }
- catch(InterruptedException interruptedexception) { }
- } else
- {
- lastTime = l;
- lastCount = -32768;
- flag = true;
- }
- }
- } else
- {
- l = lastTime;
- }
- word0 = lastCount++;
- i = getHostUniqueNum();
- }
- String s = Integer.toString(i, 16) + sep + Long.toString(l, 16) + sep + Integer.toString(word0, 16);
- if(s.length() > 24)
- s = s.substring(s.length() - 24);
- return s;
- }
- public Serializable generate_old(SessionImplementor session, Object obj) {
- String name = obj.getClass().getName();
- return new StringBuffer(64)
- .append(name.substring(name.lastIndexOf('.')+1)).append(sep)
- .append((short)getIP()).append(sep)
- .append(Math.abs((short)getJVM())).append(sep)
- .append(getCount())
- .toString();
- }
- private static int getHostUniqueNum()
- {
- return (new Object()).hashCode();
- }
- public void configure(Type type, Properties params, Dialect d) {
- sep = PropertiesHelper.getString("separator", params, "");
- }
- public static void main( String[] args ) throws Exception {
- Properties props = new Properties();
- props.setProperty("separator", "");
- IdentifierGenerator gen = new UIDGenerator();
- ( (Configurable) gen ).configure(Hibernate.STRING, props, null);
- IdentifierGenerator gen2 = new UIDGenerator();
- ( (Configurable) gen2 ).configure(Hibernate.STRING, props, null);
- for ( int i=0; i<10; i++) {
- String id = (String) gen.generate(null, gen);
- System.out.println(id);
- String id2 = (String) gen2.generate(null, gen2);
- System.out.println(id2);
- }
- }
- }
这个类必须要扩展AbstractUUIDGenerator并实现Configurable接口,在generate方法中生成我们想要的主键。
在hibernate的配置文件中要做以下的配置:
xml 代码
- <id name="id" type="java.lang.String">
- <column name="id" length="24" />
- <generator class="com.gsta.eshore.framework.util.uid.UIDGenerator"><param name="separator">-</param></generator>
- </id>
Generator的类要引用UIDGenerator,并且可以带参数生成主键,示例是根据时间,Ip等生成一个24位的字符串。这样做的灵活性大大提高了,提供了最好的性能和数据库平台适应性。
但是有时候我们在保存一条记录的时候是不能指定主键的,因为它的主键要来源于其他的表的主键,(hibernate推荐用代理主键,但是有时候设计的时候没有用到)。这个时候的主键生成策略就要是assigned了。为了保持主键的连贯性,我总不能又用另外一种主键生成策略吧。
仿照上面的类,我们做一个生成24为随机字符串的类。
java 代码
- package com.gsta.eshore.framework.util.uid;
- public class UID
- {
- private static long lastTime = System.currentTimeMillis();
- private static short lastCount = -32768;
- private static Object mutex = new Object();
- private static long ONE_SECOND = 1000L;
- public UID()
- {
- }
- public static String getUID()
- {
- long l = 0L;
- short word0 = 0;
- int i = 0;
- synchronized(mutex)
- {
- if(lastCount == 32767)
- {
- for(boolean flag = false; !flag;)
- {
- l = System.currentTimeMillis();
- if(l < lastTime + ONE_SECOND)
- {
- try
- {
- Thread.currentThread();
- Thread.sleep(ONE_SECOND);
- }
- catch(InterruptedException interruptedexception) { }
- } else
- {
- lastTime = l;
- lastCount = -32768;
- flag = true;
- }
- }
- } else
- {
- l = lastTime;
- }
- word0 = lastCount++;
- i = getHostUniqueNum();
- }
- String s = Integer.toString(i, 16) + "`" + Long.toString(l, 16) + "`" + Integer.toString(word0, 16);
- if(s.length() > 24)
- s = s.substring(s.length() - 24);
- return s;
- }
- private static int getHostUniqueNum()
- {
- return (new Object()).hashCode();
- }
-
- public static void main(String[] args) {
- for (int i = 0; i < 100; i++) {
- String uid=getUID();
- System.out.println(uid);
- }
- }
- }
在save一个实体的时候调用entity.setId(UID.getUID())。
呵呵,以后用hibernate就不用烦用什么主键生成策略了,自己做一个。
<id name="id" type="java.lang.String"><column name="id" length="24"><id type="java.lang.String" name="id"><column length="24" name="id"></id></column></id>
分享到:
相关推荐
【hibernate主键生成策略】是Hibernate框架中用于生成持久化对象主键的重要机制,它决定了如何在数据库中创建唯一的标识符。在SSH(Spring、Struts、Hibernate)架构中,Hibernate作为持久层框架,主键生成策略的...
### Hibernate主键生成策略 #### 一、概述 在Hibernate框架中,主键生成策略是对象持久化过程中不可或缺的一部分。合理的主键生成机制不仅能够确保数据的唯一性,还能够提高系统的性能和可扩展性。本文将详细介绍...
### Hibernate映射主键生成策略native #### 一、引言 在ORM(对象关系映射)技术中,Hibernate作为一款流行的Java持久层框架,在处理数据持久化方面提供了丰富的功能和灵活性。其中,主键生成策略是Hibernate配置...
了解并正确选择主键生成策略对于JPA应用程序的性能和可扩展性至关重要。在实际开发中,应根据项目需求和数据库特性来确定合适的策略。 综上所述,这个压缩包提供的教程详细讲解了JPA的基本概念,以及如何通过实例...
1. 主键生成策略:映射文件中的`<generator>`元素用于指定主键生成策略,如`native`(根据数据库类型选择合适的生成策略)、`identity`(自动增长)等。 2. 数据库兼容性:不同的数据库系统有不同的数据类型,需要...
自动生成的Entity类通常包含属性(对应表的字段)和getter/setter方法,有时还会包含一些特定的Hibernate注解,如@Id(主键)和@GeneratedValue(主键生成策略)。 2. **映射文件(Mapping Files)**:在传统的...
- `@GeneratedValue`:定义主键的生成策略,如自增、序列等。 - `@ManyToOne`、`@OneToOne`、`@OneToMany`、`@ManyToMany`:用于关联映射,表示多对一、一对一、一对多、多对多的关系。 - `@JoinColumn`:用于定义...
通过对以上几种Hibernate主键生成策略的介绍与分析,我们可以看出每种策略都有其独特的适用场景和优缺点。在实际开发过程中,应根据具体需求和技术栈来合理选择主键生成策略,以达到最佳的数据处理效果。此外,随着...
2. **Hibernate配置**: 在使用Hibernate之前,开发者需要配置Hibernate的主配置文件(hibernate.cfg.xml),其中包含了数据库连接信息、方言设置、缓存策略等关键参数。 3. **实体类(po)**: 在Hibernate中,实体...
- 可自定义主键生成策略,扩展Hibernate类。 2. **普通属性(property)配置**: - `property`元素用于映射实体类的普通属性。`name`属性对应Java类的字段名,`column`指定数据库列名,其他属性如`access`、`type...
6. **Hibernate 主键生成策略**: - **Assigned**:由用户在保存对象前指定主键值,完全独立于底层数据库。 - **Hilo**:使用高低位算法,需要额外的数据库表和字段,适用于跨数据库的唯一性需求。 - **Increment...
Hibernate支持多种主键生成策略,包括但不限于: - **increment**:由Hibernate负责自增长。 - **identity**:基于数据库的自增策略。 - **sequence**:基于Oracle等数据库的序列。 - **native**:根据数据库类型...
这里,`@Table(name = "users")`表示该实体类映射到名为`users`的数据库表,`@Id`标识主键字段,`@GeneratedValue`定义主键生成策略。 3. 自动实体生成: 在MyEclipse等集成开发环境中,可以通过插件或内置工具...
而Hibernate Tool是Hibernate提供的一个扩展工具集,它可以极大地简化开发过程,尤其是当涉及到数据库与Java对象之间的映射时。本文将详细介绍如何通过Hibernate Tool来生成Java类和HBM(Hibernate Mapping)文件。 ...
除了内置的主键生成策略,开发者还可以通过扩展Hibernate的类来自定义主键生成器。这允许更灵活地控制主键的生成逻辑,满足特定业务场景的需求。具体实现细节可参考相关文档或社区资源。 总之,Hibernate映射文件的...
3. **注解**:如`@Entity`表示这是一个Hibernate实体,`@Table`指定对应数据库中的表名,`@Id`标识主键,`@GeneratedValue`处理主键生成策略。 除了实体类,生成器还会自动生成对应的Hibernate映射文件(.hbm.xml)...
在实际开发中,我们还应注意一些最佳实践,如合理设计实体类和数据库表的关系,以及选择合适的主键生成策略,以确保代码的可扩展性和性能。此外,随着技术的发展,现代Java应用可能会转向使用注解(Annotations)...