H2数据库:使用jdbcTemplate插入记录时,列"ID"不允许NULL

Gui*_* He 17 hibernate h2

我使用hibernate的hbm2ddl自动生成模式.这是我的域名:

@Entity
public class Reader {

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  Long id;

  @Column(nullable=false,unique=true)
  String name;

  @Enumerated(EnumType.STRING)
  Gender gender;

  int age;

  Date registeredDate = new Date();

// getter and setter ...
}
Run Code Online (Sandbox Code Playgroud)

当我使用hibernate来保存a时reader,它可以正常工作,因为它会产生一个id reader.但是,当我使用jdbcTemplate插入带有纯SQL的记录时,它会报告错误:

org.springframework.dao.DataIntegrityViolationException: StatementCallback; 
SQL [insert into reader(name,gender,age) values('Lily','FEMALE',21)]; 
NULL not allowed for column "ID"; 
    SQL statement:insert into reader(name,gender,age) values('Lily','FEMALE',21) [23502-192]; 
nested exception is org.h2.jdbc.JdbcSQLException: NULL not allowed for column "ID"; 
    SQL statement:  insert into reader(name,gender,age) values('Lily','FEMALE',21) [23502-192]
Run Code Online (Sandbox Code Playgroud)

怎么解决这个?

  1. 我调试发现生成的hb2ddl的DDL是create table Book (id bigint not null, author varchar(255), name varchar(255), price double not null, type varchar(255), primary key (id)).似乎嫌疑人以自己的方式处理了这个问题,但是如何处理?
  2. @GeneratedValue(strategy=GenerationType.AUTO)应产生auto increment的DDL的语句,但我没有发现.我错过了吗?

Sta*_*avL 22

尝试使用strategy=GenerationType.IDENTITY而不是strategy=GenerationType.AUTO

也可能是错误的hibernate.dialect试试

hibernate.dialect=org.hibernate.dialect.H2Dialect
Run Code Online (Sandbox Code Playgroud)

  • 谢谢.当我改为`strategy = GenerationType.IDENTITY`时,它有效.并且DDL子句现在更改为`create table Reader(id bigint默认生成为identity,age integer not null,gender varchar(255),name varchar(255)not null,registeredDate timestamp,primary key(id))`.那么`IDENTITY`和`AUTO`之间的区别是什么? (3认同)
  • **IDENTITY**表示持久性提供程序必须使用数据库标识列为实体分配主键.**AUTO**表示持久性提供程序应为特定数据库选择适当的策略.<code> AUTO </ code>生成策略可能期望存在数据库资源,或者它可能尝试创建数据库资源.供应商可以提供有关如何在不支持模式生成或无法在运行时创建模式资源的情况下创建此类资源的文档. (3认同)

小智 22

如果您使用 H2 依赖项版本:“ 2.0.202 ”或更高版本,那么其他 2 种方法可能会起作用。

1:使用H2版本:“ 1.4.200 ”('com.h2database:h2:1.4.200')

2:将“ ;MODE=LEGACY ”附加到 JDBC url ( test case -> jdbc:h2:mem:test;MODE=LEGACY)

  • 谢谢,[方法2](https://github.com/tarent/timestamp-utc/commit/a42b21e0665e7c7d86d3f4b341b78c7497570cce)确实有效!显然,H2“安全”更新破坏了其功能? (3认同)

GKi*_*lin 8

如果DB支持一个序列,Hibernate 5.2.x(Spring Boot 2.x)会更改序列的默认策略。因此,根据此顺序,必须创建with strategy=GenerationType.AUTOhibernate_sequenceid不会自动递增,如下所示:

create table users (id integer not null, ...) 
Run Code Online (Sandbox Code Playgroud)

代替

create table table_name(id int default hibernate_sequence.nextval primary key, ...);
Run Code Online (Sandbox Code Playgroud)

(请参阅HHH-13268)。有几种解决方案:

  • 更改@GeneratedValuestrategy = GenerationType.IDENTITY
  • 设置spring.jpa.properties.hibernate.id.new_generator_mappings=false(spring-boot别名spring.jpa.hibernate.use-new-id-generator-mappings
  • 用nextval插入: INSERT INTO TABLE(ID, ...) VALUES (hibernate_sequence.nextval, ...)


Mar*_*idt 7

这个问题已在 Hibernate 5.6.5 (Spring Boot 2.6.4) 中得到解决,因此 H2 版本 2.0.202(或更高版本)可以再次工作。

请参阅https://github.com/hibernate/hibernate-orm/pull/4524以供参考。