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

H2 database: NULL not allowed for column "ID" when inserting record using jdbcTemplate

我使用 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 ...
}

当我使用 hibernate 保存 reader 时,它按预期工作正常,因为它为 reader 生成了一个 id。但是当我用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]

如何解决?

  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))。 hiberate 似乎以自己的方式处理 id 策略,但是如何处理?
  2. @GeneratedValue(strategy=GenerationType.AUTO) 应该在 DDL 的语句中生成 auto increment 但我没有找到。我错过了吗?

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

也可能是错的hibernate.dialect 试试

hibernate.dialect=org.hibernate.dialect.H2Dialect

Hibernate 5.2.x (Spring Boot 2.x) 如果 DB 支持,则更改序列的默认策略。因此,使用 strategy=GenerationType.AUTO,创建 hibernate_sequence,但 id 不会自动递增,基于此序列,必须是:

create table users (id integer not null, ...) 

而不是

create table table_name(id int default hibernate_sequence.nextval primary key, ...);

(参见 HHH-13268)。有几种解决方法:

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

如果您使用的是 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)

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

参考https://github.com/hibernate/hibernate-orm/pull/4524