Oracle序列在Java Hibernate与SQL Developer中返回值不一致问题
兄弟,我之前碰到过几乎一模一样的坑!这问题大概率是两个原因之一,咱们挨个排查:
1. 先确认:Hibernate是不是用错了序列?
看你贴的日志,Hibernate执行的查询是:
select SPS_PARAM_ID_SEQUENCE.nextval from dual
但你提供的序列详情里,序列名是PARAM_ID_SEQUENCE——少了SPS_前缀!这说明Hibernate在调用另一个完全不同的序列,而不是你在SQL Developer里查的那个!
你赶紧在SQL Developer里查一下SPS_PARAM_ID_SEQUENCE的信息:
select * from user_sequences where sequence_name = 'SPS_PARAM_ID_SEQUENCE';
看看它的LAST_NUMBER是不是接近1177248345 / 30(因为你的allocationSize是30),或者直接执行select SPS_PARAM_ID_SEQUENCE.nextval from dual,肯定会得到和Hibernate返回值对应的数值。
如果是这个问题,只要把@SequenceGenerator里的sequenceName改成正确的SPS_PARAM_ID_SEQUENCE就搞定了!
2. 如果序列名没问题,那就是Hibernate和Oracle序列的配置不匹配
你的Hibernate注解里设置了allocationSize = 30,但Oracle序列的INCREMENT_BY = 1、CACHE_SIZE = 20,这俩的逻辑冲突了:
Hibernate的allocationSize是告诉它:「每次从数据库拿1个序列值,我可以用这个值生成连续的30个ID(比如拿了X,就用X、X+1…X+29)」——但这个逻辑要求Oracle序列的INCREMENT_BY必须等于allocationSize,这样每次Hibernate拿的X,正好是下一批30个ID的起始值。
但你的序列INCREMENT_BY是1,每次只加1,Hibernate就会把这个X当成「批次号」,然后用initialValue + (X-1)*allocationSize + 偏移量来计算ID,结果就是你看到的:Hibernate返回的ID是数据库序列值的30倍左右。
解决方法二选一:
- 方法一:改Hibernate配置:把
@SequenceGenerator的allocationSize改成1,和Oracle序列的INCREMENT_BY保持一致:@SequenceGenerator(name = "PARAM_ID_SEQUENCE", initialValue = 10, allocationSize = 1, sequenceName = "PARAM_ID_SEQUENCE") - 方法二:改Oracle序列:把序列的
INCREMENT_BY改成30,同时CACHE_SIZE设为30的倍数(比如30、60),和Hibernate的allocationSize匹配:ALTER SEQUENCE PARAM_ID_SEQUENCE INCREMENT BY 30 CACHE 30;
注意:你的initialValue = 10已经没用了,因为序列当前值远大于10,Hibernate会忽略这个参数,以数据库序列的实际值为准。
验证一下:改完配置重启应用,生成一个新ID,再去SQL Developer查序列的nextval,数值就能对应上了!
内容的提问来源于stack exchange,提问作者Abe

