JPA/Hibernate操作Oracle:持久化实体时跳过自动生成ID列问题
Oracle 11g+Hibernate的IDENTITY主键保存问题解决方案
环境信息
- Oracle数据库实际版本:11g(配置标注为19)
- Hibernate版本:5.5.4
- 使用方言:
org.hibernate.dialect.Oracle12cDialect - JDBC驱动版本:12.2.0.1
问题场景与报错
需通过JPA/Hibernate保存带有自动生成ID列(PROT_ID)的实体,数据库表创建语句如下:
CREATE TABLE SOME_PROTOCOL( PROT_ID NUMBER(18) GENERATED ALWAYS AS IDENTITY (START WITH 123 MAXVALUE 99999) NOT NULL, MORE_COLS VARCHAR2(500 CHAR) NOT NULL);
手动插入时需跳过ID列,正确语句为:
insert into SOME_PROTOCOL (MORE_COLS) values ('Some Value');
对应的实体类代码:
@Entity @Table(name = "SOME_PROTOCOL") public class SomeProtocol { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "PROT_ID", insertable = false) private Long id; // Getter, Setter, 其他字段 }
执行保存操作:
SomeProtocol s = new SomeProtocol(); s.setMoreCols("whatever"); hibernateSession.save(s);
出现报错:
ERROR: Invalid argument(s) in call Hibernate: insert into APPL_PROTOCOL (PROT_ID, MORE_COLS) values (default, ?)
JPA并未跳过ID列,反而传入default值,尝试@Column(insertable=false)、GenerationType.AUTO均无法解决问题。
解决方案
将表的ID生成方式改为外部序列,即可让Hibernate正常保存实体。修改后的实体类ID字段代码如下:
@SequenceGenerator(name = "SEQ_APPL_PROT_GENERATOR", sequenceName = "SEQ_APPL_PROTOCOL_ID", allocationSize = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_APPL_PROT_GENERATOR") @Column(name = "PROT_ID") private Long id;
内容的提问来源于stack exchange,提问作者Bernie
相关产品推荐
相关产品推荐

