hibernate中的@GeneratedValue与@GenericGenerator

栏目: Hibernate · 发布时间: 7年前

内容简介:hibernate中的@GeneratedValue与@GenericGenerator

1、GeneratedValue与GenericGenerator的区别

@GeneratorValue注解----JPA通用策略生成器

@GenericGenerator注解----自定义主键生成策略

一个是通用的一个是自定义的这就是他们的区别。

2、@GeneratorValue注解----JPA通用策略生成器

GeneratorValue 属于一个JPA接口,其接口下包含了两个抽象的参数,GenerationType类型的strategy和String类型的generator,并且两个参数都有相应的默认值。

@Target({METHOD,FIELD})    

    @Retention(RUNTIME)    

    public @interface GeneratedValue{    

        GenerationType strategy() default AUTO;    
        String generator() default "";    

    }

1.generator  : String  //JPA 持续性提供程序为它选择的主键生成器分配一个名称,如果该名称难于处理、是一个保留字、与事先存在的数据模型不兼容或作为数据库中的主键生成器名称无效,则将 generator 设置为要使用的 String 生成器名称。
例如用hibernate的uuid主键生成器就如下来写:

@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid.hex")

2.strategy    : String  // 指定生成策略

其中GenerationType: 

public enum GenerationType{    

    TABLE,    

    SEQUENCE,    

    IDENTITY,    

    AUTO   

}

可以看出JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO. 


TABLE:使用一个特定的数据库表格来保存主键。 
SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。 
IDENTITY:主键由数据库自动生成(主要是自动增长型) 
AUTO:主键由程序控制。 

1、TABLE

使用一个特定的数据库表格来保存主键,持久化引擎通过关系数据库的一张特定的表格来生成主键,这种策略的好处就是不依赖于外部环境和数据库的具体实现,在不同数据库间可以很容易的进行移植,但由于其不能充分利用数据库的特性,所以不会优先使用。该策略一般与另外一个注解一起使用@TableGenerator,@TableGenerator注解指定了生成主键的表(可以在实体类上指定也可以在主键字段或属性上指定),然后JPA将会根据注解内容自动生成一张表作为序列表(或使用现有的序列表)。如果不指定序列表,则会生成一张默认的序列表,表中的列名也是自动生成,数据库上会生成一张名为sequence的表(SEQ_NAME,SEQ_COUNT)。序列表一般只包含两个字段:第一个字段是该生成策略的名称,第二个字段是该关系表的最大序号,它会随着数据的插入逐渐累加。

示例:

User实体类:

package com.fendo.Entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.TableGenerator;


@Entity
@Table(name="USER_TABLE")
public class UserEntity {
	
	
	private Integer uid;
	private String uname;
	private String uage;
	private String usex;
	private String usom;
	
	@Id
	@Column(name="id")
	@GeneratedValue(strategy=GenerationType.TABLE,generator="table_gen")
	@TableGenerator(
			name = "table_gen",  
		    table="fendo_generator",  
		    pkColumnName="seq_name",     //指定主键的名字
		    pkColumnValue="fendos",      //指定下次插入主键时使用默认的值
		    valueColumnName="seq_id",    //该主键当前所生成的值,它的值将会随着每次创建累加
		    initialValue = 1,            //初始化值
		    allocationSize=1             //累加值
		    )
	public Integer getUid() {
		return uid;
	}
	public void setUid(Integer uid) {
		this.uid = uid;
	}
	
	@Column(name="uname")
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	
	@Column(name="uage")
	public String getUage() {
		return uage;
	}
	public void setUage(String uage) {
		this.uage = uage;
	}
	
	@Column(name="usex")
	public String getUsex() {
		return usex;
	}
	public void setUsex(String usex) {
		this.usex = usex;
	}
	
	@Column(name="usom")
	public String getUsom() {
		return usom;
	}
	public void setUsom(String usom) {
		this.usom = usom;
	}
}

表字段:

hibernate中的@GeneratedValue与@GenericGenerator

对应的 SQL 文件:

CREATE TABLE `user_table` (
  `id` int(11) NOT NULL,
  `uage` varchar(255) DEFAULT NULL,
  `uname` varchar(255) DEFAULT NULL,
  `usex` varchar(255) DEFAULT NULL,
  `usom` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

然后创建序列表:

hibernate中的@GeneratedValue与@GenericGenerator

并插入一条数据

INSERT INTO `fendo_generator` VALUES ('1', 'fendo');

对应的SQL文件为:

CREATE TABLE `fendo_generator` (
  `seq_id` int(11) NOT NULL,
  `seq_name` varchar(255) NOT NULL,
  PRIMARY KEY (`seq_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

和以下的代码相对应:

@GeneratedValue(strategy=GenerationType.TABLE,generator="table_gen")
@TableGenerator(
    name = "table_gen",          //name对应@GeneratedValue中generator 引用的名字
    table="fendo_generator",       //对应数据库表中的名字,表键-字段名
    pkColumnName="seq_name",       //指定主键的名字
    pkColumnValue="fendos",       //指定下次插入主键时使用默认的值,表键-字段值
    valueColumnName="seq_id",      //该主键当前所生成的值,它的值将会随着每次创建累加,表值-字段名
    initialValue = 1,           //初始化值
    allocationSize=1            //累加值,每次累加1
)

@TableGenerator的定义为:

@Target({TYPE, METHOD, FIELD})   

@Retention(RUNTIME)  

public @interface TableGenerator {  

  String name();  

  String table() default "";  

  String catalog() default "";  

  String schema() default "";  

  String pkColumnName() default "";  

  String valueColumnName() default "";  

  String pkColumnValue() default "";  

  int initialValue() default 0;  

  int allocationSize() default 50;  

  UniqueConstraint[] uniqueConstraints() default {};  

}

属性说明: 


name属性表示该表主键生成策略的名称,它被引用在@GeneratedValue中设置的“generator”值中。 


table属性表示表生成策略所持久化的表名,例如,这里表使用的是数据库中的“fendo_generator”。


catalog属性和schema具体指定表所在的目录名或是数据库名。 


pkColumnName属性的值表示在持久化表中,该主键生成策略所对应键值的名称。例如在“ fendo_generator ”中将“seq_name”作为主键对应值得名称,也就是这个主键所对应的名字。如上 seq_name ”为"fendo",那么它所对应的值为"1"


valueColumnName属性的值表示在持久化表中,该主键当前所生成的值,它的值将会随着每次创建累加。例如,在“ fendo_generator ”中将“seq_id”作为主键的值 


pkColumnValue属性的值表示在持久化表中,该生成策略生成主键所对应的名字。例如在“ fendo_generator ”表中,将“ seq_name ”的值为“fendos”。


initialValue表示主键初识值,默认为0。 


allocationSize表示每次主键值增加的大小,例如设置成1,则表示每次创建新记录后自动加1,默认为50。 


UniqueConstraint与@Table标记中的用法类似。 

测试类:

public class App 
{
    public static void main( String[] args )
    {
    	SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();  
    	Session session = sessionFactory.getCurrentSession();  
    	Transaction tx = session.beginTransaction();  
        

    	UserEntity ue=new UserEntity();
    	ue.setUage("19");
    	ue.setUname("fendo");
    	ue.setUsex("男");
    	ue.setUsom("123456");
    	
        session.save(ue);  
    	
        tx.commit();
        session.close();
    }
    
   
}

第一次执行时所执行的SQL语句如下:

Hibernate: 
    select
        tbl.seq_id 
    from
        fendo_generator tbl 
    where
        tbl.seq_name=? for update
            
Hibernate: 
    insert 
    into
        fendo_generator
        (seq_name, seq_id)  
    values
        (?,?)
Hibernate: 
    update
        fendo_generator 
    set
        seq_id=?  
    where
        seq_id=? 
        and seq_name=?
Hibernate: 
    insert 
    into
        USER_TABLE
        (uage, uname, usex, usom, id) 
    values
        (?, ?, ?, ?, ?)

此时fendo_generator表就会发生变化会:

hibernate中的@GeneratedValue与@GenericGenerator

user_table会多出一条数据:

hibernate中的@GeneratedValue与@GenericGenerator

再执行一次表中的结果就会变成如下:

hibernate中的@GeneratedValue与@GenericGenerator

hibernate中的@GeneratedValue与@GenericGenerator

完整示例: http://download.csdn.net/detail/u011781521/9843151


2、SEQUENCE 

在某些数据库中,不支持主键自增长,比如Oracle,其提供了一种叫做"序列(sequence)"的机制生成主键。此时,GenerationType.SEQUENCE就可以作为主键生成策略。该策略的不足之处正好与TABLE相反,由于只有部分数据库(Oracle,PostgreSQL,DB2)支持序列对象,MYsql不支持序列,所以该策略一般不应用于其他数据库。类似的,该策略一般与另外一个注解一起使用@SequenceGenerator,@SequenceGenerator注解指定了生成主键的序列.然后JPA会根据注解内容创建一个序列(或使用一个现有的序列)。如果不指定序列,则会自动生成一个序列SEQ_GEN_SEQUENCE。

@Id  
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator="fendo_seq")  
@SequenceGenerator(name="fendo_seq", sequenceName="seq_name")

@SequenceGenerator定义:

@Target({TYPE, METHOD, FIELD})   

@Retention(RUNTIME)  

public @interface SequenceGenerator {  

 String name();  

 String sequenceName() default "";  

 int initialValue() default 0;  

 int allocationSize() default 50;  

}

属性说明:

name属性: 表示该表主键生成策略的名称,它被引用在@GeneratedValue中设置的“generator”值中。

sequenceName属性 表示生成策略用到的数据库序列名称。 

initialValue属性 表示主键初识值,默认为0。 

allocationSize属性 表示每次主键值增加的大小,例如设置成1,则表示每次创建新记录后自动加1,默认为50。


3、IDENTITY 

此种主键生成策略就是通常所说的主键自增长,数据库在插入数据时,会自动给主键赋值,比如 MySQL 可以在创建表时声明"auto_increment" 来指定主键自增长。该策略在大部分数据库中都提供了支持(指定方法或关键字可能不同),但还是有少数数据库不支持,所以可移植性略差。使用自增长主键生成策略是只需要声明strategy = GenerationType.IDENTITY即可。

@Id  
@GeneratedValue(strategy = GenerationType.IDENTITY)

需要注意的是,同一张表中自增列最多只能有一列。

4、AUTO

把主键生成策略交给持久化引擎(persistence engine),持久化引擎会根据数据库在以上三种主键生成策略中选择其中一种。此种主键生成策略比较常用,由于JPA默认的生成策略就是GenerationType.AUTO,所以使用此种策略时.可以显式的指定@GeneratedValue(strategy = GenerationType.AUTO)也可以直接@GeneratedValue。

@Id  
@GeneratedValue(strategy = GenerationType.AUTO)

在指定主键时,如果不指定主键生成策略,默认为AUTO。

@Id

跟下面的定义是一样的。   

@Id  
@GeneratedValue(strategy = GenerationType.AUTO)

3、 @GenericGenerator 注解 ----自定义主键生成策略

GenericGenerator一般配合 GeneratorValue来用比如说


Java代码  

@Id  
@GeneratedValue(GenerationType.AUTO)

可以用hibernate特有以下用法来实现 


Java代码  

@GeneratedValue(generator = "paymentableGenerator")    
@GenericGenerator(name = "paymentableGenerator", strategy = "assigned")

@GenericGenerator的定义: 

@Target({PACKAGE, TYPE, METHOD, FIELD})  

@Retention(RUNTIME)  

public @interface GenericGenerator {  

 /** 

  * unique generator name 

  */  

 String name();  

 /** 

  * Generator strategy either a predefined Hibernate 

  * strategy or a fully qualified class name. 

  */  

 String strategy();  

 /** 

  * Optional generator parameters 

  */  

 Parameter[] parameters() default {};  

}

name属性指定生成器名称。 

strategy属性指定具体生成器的类名。 

有以下参数可选:

static {  

  GENERATORS.put("uuid", UUIDHexGenerator.class);  

  GENERATORS.put("hilo", TableHiLoGenerator.class);  

  GENERATORS.put("assigned", Assigned.class);  

  GENERATORS.put("identity", IdentityGenerator.class);  

  GENERATORS.put("select", SelectGenerator.class);  

  GENERATORS.put("sequence", SequenceGenerator.class);  

  GENERATORS.put("seqhilo", SequenceHiLoGenerator.class);  

  GENERATORS.put("increment", IncrementGenerator.class);  

  GENERATORS.put("foreign", ForeignGenerator.class);  

  GENERATORS.put("guid", GUIDGenerator.class);  

  GENERATORS.put("uuid.hex", UUIDHexGenerator.class); //uuid.hex is deprecated  

  GENERATORS.put("sequence-identity", SequenceIdentityGenerator.class);  

}


1、native

@GeneratedValue(generator = "fendo_Generator")    
@GenericGenerator(name = "fendo_Generator", strategy = "native")


@GeneratedValue(generator = "fendo_Generator")    
@GenericGenerator(name = "fendo_Generator", strategy = "uuid")

3、hilo

@GeneratedValue(generator = "fendo_Generator")    
@GenericGenerator(name = "fendo_Generator", strategy = "hilo")

4、assigned 

@GeneratedValue(generator = "fendo_Generator")    
@GenericGenerator(name = "fendo_Generator", strategy = "assigned")

5、identity

@GeneratedValue(generator = "fendo_Generator")    
@GenericGenerator(name = "fendo_Generator", strategy = "identity")

6、select 

@GeneratedValue(generator = "fendo_Generator")  
@GenericGenerator(name="fendo_Generator", strategy="select",  
     parameters = { @Parameter(name = "key", value = "idstoerung") })

7、sequence

@GeneratedValue(generator = "fendo_Generator")  
@GenericGenerator(name = "fendo_Generator", strategy = "sequence",   
         parameters = { @Parameter(name = "sequence", value = "seq_sum") })

8、seqhilo

@GeneratedValue(generator = "fendo_Generator")  
@GenericGenerator(name = "fendo_Generator", strategy = "seqhilo",   
         parameters = { @Parameter(name = "max_lo", value = "5") })

9、increment

@GeneratedValue(generator = "fendo_Generator")    
@GenericGenerator(name = "fendo_Generator", strategy = "increment")

10、foreign

@GeneratedValue(generator = "fendo_Generator")  
@GenericGenerator(name = "fendo_Generator", strategy = "foreign",   
         parameters = { @Parameter(name = "property", value = "employee") })

注意:直接使用@PrimaryKeyJoinColumn

@OneToOne(cascade = CascadeType.ALL)   
@PrimaryKeyJoinColumn

例如

@Entity  
public class Employee {  
  @Id 
  Integer id;  
      
  @OneToOne 
  @PrimaryKeyJoinColumn  
  EmployeeInfo info;  
  ...  
} 

应该为

@Entity  
public class Employee {  
  @Id   
  @GeneratedValue(generator = "fendo_Generator")  
  @GenericGenerator(name = "fendo_Generator", strategy = "foreign",   
         parameters = { @Parameter(name = "property", value = "info") })   
  Integer id;  
      
  @OneToOne  
  EmployeeInfo info;  
  ...  
}

11、guid

@GeneratedValue(generator = "fendo_Generator")    
@GenericGenerator(name = "fendo_Generator", strategy = "guid")

12、uuid.hex

@GeneratedValue(generator = "fendo_Generator")    
@GenericGenerator(name = "fendo_Generator", strategy = "uuid.hex")

13、sequence-identity

@GeneratedValue(generator = "fendo_Generator")  
@GenericGenerator(name = "fendo_Generator", strategy = "sequence-identity",   
         parameters = { @Parameter(name = "sequence", value = "seq_sum") })

5、四种数据库的支持情况如下

数据库名称 支持的id策略
MySQL

GenerationType.TABLE

GenerationType.AUTO

GenerationType.IDENTITY

不支持GenerationType.SEQUENCE

Oracle

strategy=GenerationType.AUTO

GenerationType.SEQUENCE

GenerationType.TABLE

不支持GenerationType.IDENTITY

postgreSQL

GenerationType.TABLE

GenerationType.AUTO

GenerationType.IDENTITY

GenerationType.SEQUENCE

都支持

kingbase

GenerationType.TABLE

GenerationType.SEQUENCE

GenerationType.IDENTITY

GenerationType.AUTO

都支持


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Data Mining

Web Data Mining

Bing Liu / Springer / 2006-12-28 / USD 59.95

Web mining aims to discover useful information and knowledge from the Web hyperlink structure, page contents, and usage data. Although Web mining uses many conventional data mining techniques, it is n......一起来看看 《Web Data Mining》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码