@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;
- }
- }
表字段:
对应的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;
然后创建序列表:
并插入一条数据
- 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表就会发生变化会:
user_table会多出一条数据:
再执行一次表中的结果就会变成如下:
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属性指定具体生成器的类名。
parameters得到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);
- }
上面十二种策略,加上native,hibernate一共默认支持十三种生成策略。
1、native
- @GeneratedValue(generator = "fendo_Generator")
- @GenericGenerator(name = "fendo_Generator", strategy = "native")
2、uuid
- @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 都支持 |
@GeneratedValue与@GenericGenerator区别相关推荐
- 关于@GeneratedValue和@GenericGenerator的学习笔记
一.JPA通用策略生成器 说实话注解并没有完全理解,此笔记整理略乱. 通过annotation来映射hibernate实体的,基于annotation的hibernate主键标识为@Id, 其生成规则 ...
- 全网最全精析破解 Springboot+Jpa 对数据库增删改查
前言: 昨天做的是springboot+mybatis 对数据库进行增删改查 但是我感觉配置文件太多了 很麻烦 繁琐 今天搞一下springboot+Jpa对数据库进行增删改查, 感觉很好用 ,所以记 ...
- Java Persistence API中的FetchType LAZY和EAGER之间的区别?
我是Java Persistence API和Hibernate的新手. Java Persistence API中的FetchType.LAZY和FetchType.EAGER什么区别? #1楼 我 ...
- hibernate中@Entity和@Table的区别
Java Persistence API定义了一种定义,可以将常规的普通Java对象(有时被称作POJO)映射到数据库. 这些普通Java对象被称作Entity Bean. 除了是用Java Pers ...
- 文档 修订 非修订区别_修订和不变性
文档 修订 非修订区别 这是一个简短的帖子. 我不确定如何启动它. 这是审阅一些现有代码时"为什么我没有想到这一刻"之一. 由于存在NDA,我无法共享实际代码. 它与处理修订有关. ...
- Java文档阅读笔记-JPA中getOne()和findById的区别
findById()和getOne()都是从数据库中检索某个对象,不过获取数据的方式是不同的,getOne()是lazy操作,这种操作甚至没有访问数据库. getOne() 返回ID的引用对象,他内部 ...
- 理解JPA注解@GeneratedValue
一.JPA通用策略生成器 通过annotation来映射hibernate实体的,基于annotation的hibernate主键标识为@Id, 其生成规则由@GeneratedValue设定的.这里 ...
- java generatedvalue_java-@GeneratedValue和@GenericGen之间的区别
扩展@ kevin-bowersox的答案. 分别在native中指定的Hibernate主键生成策略与特定生成器之间的关系 static { GENERATORS.put("uuid&qu ...
- CLOB与BLOB的区别及用途
BLOB和CLOB都是大字段类型,BLOB是按二进制来存储的,而CLOB是可以直接存储文字的. 其实两个是可以互换的的,或者可以直接用LOB字段代替这两个.但是为了更好的管理 ORACLE数据库, 通 ...
最新文章
- SpringBoot 整合:Redis延时队列的简单实现(基于有赞的设计)
- vi vim 插入 删除 修改 文本
- docker搭建harbor私有镜像库
- 房地产企业大量海外融资,或将来资不抵债,被收购
- 使用svn diff的-r参数的来比较任意两个版本的差异
- wp7开发官方教程和开发包
- HDU 4487 Maximum Random Walk
- 艾伟:ASP.NET 与 AJAX的实现方式
- finditerable 转list_Iterable/Iterator 转 list
- 消防管件做的机器人图片_看图猜管件
- Android P环境 bootchart使用
- NumPy用户指南(2)——安装NumPy
- iOS 抓包工具限免,速度下载!【附使用教程】
- HDU5832(大数取模-秦九昭算法)
- 【华人学者风采】于非 加拿大卡尔顿大学
- Contest 1479 2018-ZZNU-ACM集训队 夏季队内积分赛 (3)K题(易水寒)
- 【群晖NAS】真·免费内网穿透方案 及踩坑合集
- Mac重装系统出错的心路历程
- 实战案例分享:我用 Python 预测房价走势
- 想了3年,实现只用了3个月
热门文章
- 书籍是人类进步的阶梯
- win10、win11中Elan触摸板滚动方向反转、启动“双指点击打开右键菜单“、“双指滚动“
- Windows7旗舰版安装Pytorch(CPU版)
- 自学者福利!知乎上已获千赞,原理+实战+视频+源码
- 【陈工笔记】# Anaconda 虚拟环境中的简单操作指令#
- 广州电子厂房净化工程_广州车间厂房净化工程哪家好优惠报价“本信息长期有效”...
- 多媒体计算机中发出声音有两种来源,多媒体计算机的声音信息处理.pdf
- 渲染TA实战:冰面效果制作分享
- Mysql场景刷数据库脚本方法和顺序
- Java实现简易的界面通讯录