1、触发事件
- 在电脑A上敲项目代码,数据库原始资料是直接使用别人写好的sql导入(建表和导入表数据等);
- 将电脑A上数据库的资料,使用PL/SQL Developer导出项目中所用表(此时未导出Oracle数据库的序列user_sequences);
- 将导出的表导入到电脑B的数据库中;
- 在电脑B中运行项目,在持久化某个实例时发生异常 " org.springframework.dao.InvalidDataAccessResourceUsageException: could not get next sequence value; SQL [select SEQ_SYS_JOB.nextval from dual]; nested exception is org.hibernate.exception.SQLGrammarException: could not get next sequence value "
2、知之为知之
广大网友的力量是无穷无尽的,本文相关知识点参考链接:
2.1 什么是sequence
序列(SEQUENCE)其实是序列号生成器,可以为表中的行自动生成序列号,产生一组等间隔的数值(类型为数字)。
其主要的用途是生成表的主键值,可以在插入语句中引用,也可以通过查询检查当前值,或使序列增至下一个值。
2.2 Hibernate和sequence的关系
我们已经知道,sequence可以用来生成表中每条记录的主键,这意味着你对于主键的自增长不需要过多地管理,你每添加一个数据,它就会自动为你的主键字段进行赋值。
而Hibernate作为持久化作用的框架,在进行数据保存到表的过程中,就可以采取sequence方式来作为主键的一种生成策略。当然, 这有两个方面的工作需要你去做:
- 在 *.hbm.xml 中对于你希望采用sequence序列生成主键的字段,进行配置<generator class ...> (如上图红框标记处)
- 采用数据库提供的sequence机制生成主键,需要数据库支持sequence,如Oralce、DB、SAP DB、PostgerSQL 等,但是MySQL并不支持(可以使用identity)
2.3 Oracle中sequence的用法
2.3.1 创建序列
创建序列需要CREATE SEQUENCE系统权限。序列的创建语法如下:
CREATE SEQUENCE 序列名 [INCREMENT BY n] [START WITH n] [{MAXVALUE/ MINVALUE n|NOMAXVALUE}] [CYCLE|NOCYCLE] [{CACHE n|NOCACHE}];
1
1
CREATE SEQUENCE 序列名 [INCREMENT BY n] [START WITH n] [{MAXVALUE/ MINVALUE n|NOMAXVALUE}] [CYCLE|NOCYCLE] [{CACHE n|NOCACHE}];
- INCREMENT BY:用于定义序列的步长,如果省略,则默认为1,如果出现负值,则代表序列的值是按照此步长递减的
- START WITH:定义序列的初始值(即产生的第一个值),默认为1
- MAXVALUE:定义序列生成器能产生的最大值。选项NOMAXVALUE是默认选项,代表没有最大值定义
- MINVALUE:定义序列生成器能产生的最小值。选项NOMAXVALUE是默认选项,代表没有最小值定义
- CYCLE 和 NOCYCLE:表示当序列生成器的值达到限制值后是否循环,CYCLE代表循环,NOCYCLE代表不循环。如果不循环,达到限制值后,继续产生新值就会发生错误
- CACHE 和 NOCACHE:定义存放序列的内存块的大小,默认为20。NOCACHE表示不对序列进行内存缓冲。对序列进行内存缓冲,可以改善序列的性能
2.3.2 查看序列
SELECT * FROM USER_SEQUENCES;
1
1
SELECT * FROM USER_SEQUENCES;
2.3.3 删除序列
DROP SEQUENCE 序列名;
1
1
DROP SEQUENCE 序列名;
2.4 解决异常could not get next sequence value
在使用hibernate保存数据的时候,出现了could not get next sequence value这个错误,这个错误的意思就是找不到序列中的下一个值.
那么你需要做的是:
- 确定主键生成策略,到相应的表的 *.hbm.xml文件查看指明使用了的是哪个sequence(如本例图中所示的 SEQ_SYS_JOB)
- 登录Oracle数据库,然后查看该用户下是否存在该指明的sequence(SELECT * FROM USER_SEQUENCES;)
- 如果没有sequence,则需要到相应的用户下的创建该sequence(CREATE SEQUENCE 序列名;)
- 如果该数据表中已经有值的话,还是会出现上面那个问题,因为sequence的CURRVAL值可能不符合next value(详见 、)
最终,异常就这样解决了,皆大欢喜。