web-dev-qa-db-fra.com

Base de données H2: NULL non autorisé pour la colonne "ID" lors de l'insertion d'un enregistrement avec jdbcTemplate

J'utilise hbm2ddl de hibernate pour générer le schéma automatiquement. Voici mon domaine:

@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 ...
}

Lorsque j'utilise Hibernate pour enregistrer une reader, cela fonctionne correctement, car il génère un id pour reader. Cependant, lorsque j'utilise jdbcTemplate pour insérer un enregistrement avec du SQL pur, il signale une erreur:

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]

Comment résoudre ceci?

  1. Je débogue pour trouver que le DDL de hb2ddl généré est create table Book (id bigint not null, author varchar(255), name varchar(255), price double not null, type varchar(255), primary key (id)). Il semble que l'hiberate gère la stratégie d'identification à sa manière, mais comment?
  2. La @GeneratedValue(strategy=GenerationType.AUTO) devrait générer auto increment dans l'instruction de la DDL, mais je ne l'ai pas trouvée. Est-ce que je l'ai raté?
11
Guisong He

Essayez d'utiliser strategy=GenerationType.IDENTITY au lieu du strategy=GenerationType.AUTO

Hibernate.dialect Pourrait également être faux. Essayez le 

hibernate.dialect=org.hibernate.dialect.H2Dialect
15
StanislavL

Hibernate 5.2.x (Spring Boot 2.x) modifie la stratégie par défaut pour les séquences, si la base de données en prend en charge une. Donc, avec strategy=GenerationType.AUTO, hibernate_sequence est créé, mais id n'est pas auto-incrémenté, en fonction de cette séquence, comme il se doit:

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

au lieu de

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

(voir HHH-13268 ). Il y a plusieurs solutions:

  • remplacez @GeneratedValue par strategy = GenerationType.IDENTITY
  • set spring.jpa.properties.hibernate.id.new_generator_mappings=false (alias spring-boot spring.jpa.hibernate.use-new-id-generator-mappings)
  • insérer avec nextval: INSERT INTO TABLE(ID, ...) VALUES (hibernate_sequence.nextval, ...)
1
GKislin