Hibernate: "Le champ 'id' n'a pas de valeur par défaut"

130

Je suis confronté à ce que je pense être un problème simple avec Hibernate, mais je ne peux pas le résoudre (les forums Hibernate étant inaccessibles n'aide certainement pas).

J'ai une classe simple que j'aimerais persister, mais continuez à obtenir:

SEVERE: Field 'id' doesn't have a default value
Exception in thread "main" org.hibernate.exception.GenericJDBCException: could not insert: [hibtest.model.Mensagem]
    at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
    [ a bunch more ]
Caused by: java.sql.SQLException: Field 'id' doesn't have a default value
    [ a bunch more ]

Le code pertinent pour la classe persistante est:

package hibtest.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Mensagem  {
    protected Long id;

    protected Mensagem() { }

    @Id
    @GeneratedValue
    public Long getId() {
        return id;
}

    public Mensagem setId(Long id) {
        this.id = id;
        return this;
    }
}

Et le code en cours d'exécution est tout simplement clair:

SessionFactory factory = new AnnotationConfiguration()
    .configure()
    .buildSessionFactory();

{
    Session session = factory.openSession();
    Transaction tx = session.beginTransaction();

    Mensagem msg = new Mensagem("YARR!");

    session.save(msg);

    tx.commit();
    session.close();
}

J'ai essayé quelques «stratégies» dans l' GeneratedValueannotation mais cela ne semble tout simplement pas fonctionner. L'initialisation idn'aide pas non plus! (par exemple Long id = 20L).

Quelqu'un pourrait-il faire la lumière?

EDIT 2: confirmé: jouer avec @GeneratedValue(strategy = GenerationType.XXX)ne le résout pas

RESOLU: recréer la base de données a résolu le problème

André Chalella
la source
Quelle est la source du constructeur utilisant String?
Michael Pralow
Désolé, j'ai omis cela. Initialise simplement un champ String avec la valeur passée.
André Chalella
1
Comment générez-vous les ID côté base de données?
James McMahon
5
THX ! Jamais pensé à recréer la base de données n'était nécessaire lors du changement des stratégies. :-)
Jan Goyvaerts
1
J'ai changé GenerationTypeà @GeneratedValuepartir IDENTITYde AUTOet cela a fonctionné pour moi. En outre, vous pouvez définir une propriété d'incrémentation automatique dans MySQL.
Vishrant

Réponses:

113

Parfois, les modifications apportées au modèle ou à l'ORM peuvent ne pas être reflétées avec précision dans la base de données, même après l'exécution de SchemaUpdate.

Si l'erreur semble manquer d'explication sensée, essayez de recréer la base de données (ou au moins d'en créer une nouvelle) et de l'échafauder avec SchemaExport.

André Chalella
la source
13
Dans de nombreux cas, ce problème peut également être résolu en supprimant simplement la ou les tables incriminées, en supposant qu'Hibernate est configuré pour créer / gérer automatiquement le schéma de base de données. Pour supprimer des tables d'un schéma géré, SET foreign_key_checks = 0;c'est votre ami. Assurez SET foreign_key_checks = 1;-vous simplement que vous avez terminé.
2012
J'ai eu le même problème et j'ai essayé avec votre réponse, mais j'ai encore eu la même erreur quelle erreur je ne sais pas ... J'utilise la base de données mysql.
Krunal Patel
56

Si vous voulez que MySQL produise automatiquement des clés primaires, vous devez le dire lors de la création de la table. Vous n'êtes pas obligé de faire cela dans Oracle.

Sur la clé primaire, vous devez inclure AUTO_INCREMENT. Voir l'exemple ci-dessous.

CREATE TABLE `supplier`  
(  
  `ID` int(11) NOT NULL **AUTO_INCREMENT**,  
  `FIRSTNAME` varchar(60) NOT NULL,  
  `SECONDNAME` varchar(100) NOT NULL,  
  `PROPERTYNUM` varchar(50) DEFAULT NULL,  
  `STREETNAME` varchar(50) DEFAULT NULL,  
  `CITY` varchar(50) DEFAULT NULL,  
  `COUNTY` varchar(50) DEFAULT NULL,  
  `COUNTRY` varchar(50) DEFAULT NULL,  
  `POSTCODE` varchar(50) DEFAULT NULL,  
  `HomePHONENUM` bigint(20) DEFAULT NULL,  
  `WorkPHONENUM` bigint(20) DEFAULT NULL,  
  `MobilePHONENUM` bigint(20) DEFAULT NULL,  
  `EMAIL` varchar(100) DEFAULT NULL,  
  PRIMARY KEY (`ID`)  
) 

ENGINE=InnoDB DEFAULT CHARSET=latin1;  

Voici l'entité

package com.keyes.jpa;  

import java.io.Serializable;
import javax.persistence.*;
import java.math.BigInteger;

/**
 * The persistent class for the parkingsupplier database table.
 * 
 */
@Entity
@Table(name = "supplier")
public class supplier implements Serializable
{
  private static final long serialVersionUID = 1L;

  @Id
  **@GeneratedValue(strategy = GenerationType.IDENTITY)**
  @Column(name = "ID")
  private long id;

  @Column(name = "CITY")
  private String city;

  @Column(name = "COUNTRY")
  private String country;

  @Column(name = "COUNTY")
  private String county;

  @Column(name = "EMAIL")
  private String email;

  @Column(name = "FIRSTNAME")
  private String firstname;

  @Column(name = "HomePHONENUM")
  private BigInteger homePHONENUM;

  @Column(name = "MobilePHONENUM")
  private BigInteger mobilePHONENUM;

  @Column(name = "POSTCODE")
  private String postcode;

  @Column(name = "PROPERTYNUM")
  private String propertynum;

  @Column(name = "SECONDNAME")
  private String secondname;

  @Column(name = "STREETNAME")
  private String streetname;

  @Column(name = "WorkPHONENUM")
  private BigInteger workPHONENUM;

  public supplier()
  {
  }

  public long getId()
  {
    return this.id;
  }

  public void setId(long id)
  {
    this.id = id;
  }

  public String getCity()
  {
    return this.city;
  }

  public void setCity(String city)
  {
    this.city = city;
  }

  public String getCountry()
  {
    return this.country;
  }

  public void setCountry(String country)
  {
    this.country = country;
  }

  public String getCounty()
  {
    return this.county;
  }

  public void setCounty(String county)
  {
    this.county = county;
  }

  public String getEmail()
  {
    return this.email;
  }

  public void setEmail(String email)
  {
    this.email = email;
  }

  public String getFirstname()
  {
    return this.firstname;
  }

  public void setFirstname(String firstname)
  {
    this.firstname = firstname;
  }

  public BigInteger getHomePHONENUM()
  {
    return this.homePHONENUM;
  }

  public void setHomePHONENUM(BigInteger homePHONENUM)
  {
    this.homePHONENUM = homePHONENUM;
  }

  public BigInteger getMobilePHONENUM()
  {
    return this.mobilePHONENUM;
  }

  public void setMobilePHONENUM(BigInteger mobilePHONENUM)
  {
    this.mobilePHONENUM = mobilePHONENUM;
  }

  public String getPostcode()
  {
    return this.postcode;
  }

  public void setPostcode(String postcode)
  {
    this.postcode = postcode;
  }

  public String getPropertynum()
  {
    return this.propertynum;
  }

  public void setPropertynum(String propertynum)
  {
    this.propertynum = propertynum;
  }

  public String getSecondname()
  {
    return this.secondname;
  }

  public void setSecondname(String secondname)
  {
    this.secondname = secondname;
  }

  public String getStreetname()
  {
    return this.streetname;
  }

  public void setStreetname(String streetname)
  {
    this.streetname = streetname;
  }

  public BigInteger getWorkPHONENUM()
  {
    return this.workPHONENUM;
  }

  public void setWorkPHONENUM(BigInteger workPHONENUM)
  {
    this.workPHONENUM = workPHONENUM;
  }

}
Greg Keyes
la source
13

vous devez utiliser update dans votre propriété hbm2ddl. apportez les modifications et mettez-le à jour en Créer afin qu'il puisse créer la table.

<property name="hbm2ddl.auto">create</property>

Cela a fonctionné pour moi.

anzie001
la source
1
C'est du travail pour moi. Hibernate + Derby DB @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; Et avec la valeur createde la hbm2ddl.autopropriété, les changements appliqués dans mon schéma de base de données. Merci beaucoup ....
Adam M. Gamboa G.
12

Jetez un œil à GeneratedValuela stratégie de. Cela ressemble généralement à quelque chose comme:

@GeneratedValue(strategy=GenerationType.IDENTITY)
Steve Kuo
la source
Je vais juste suggérer ceci, essayez d'utiliser ceci au lieu de .AUTO.
James McMahon
Je dois le vérifier demain, mais je suis presque sûr que cela ne résoudra pas le problème. Je vois beaucoup de clés d'identification utilisant GenerationType.AUTO. Quoi qu'il en soit, je vais m'assurer de le tester demain.
André Chalella
Confirmé - n'aide pas
André Chalella
6

Supprimer manuellement la table de la base de données, puis réexécuter l'application a fonctionné pour moi. Dans mon cas, la table n'a pas été créée correctement (avec des contraintes) je suppose.

Sen
la source
Excellente solution. Je n'ai pas pensé de cette façon. Merci
Meir
Nous devrions le faire lorsque nous apportons des modifications à la colonne Id ou au type de génération
Jadda
5

J'ai eu ce problème. Mon erreur était que j'avais défini les fichiers insérables et actualisables comme faux et que j'essayais de définir le champ dans la demande. Ce champ est défini comme NON NULL dans DB.

@ManyToOne
@JoinColumn(name="roles_id",  referencedColumnName = "id", insertable = false, updatable = false, nullable=false)
@JsonBackReference
private Role role;

Plus tard, je l'ai changé en - insertable = true, updatable = true

@ManyToOne
@JoinColumn(name="roles_id",  referencedColumnName = "id", insertable = true, updatable = true, nullable=false)
@JsonBackReference
//@JsonIgnore
private Role role;

Cela a parfaitement fonctionné plus tard.

Kavitha yadav
la source
actualisable est vrai par défaut
Janac Meena
4

Je suis venu ici à cause du message d'erreur, il s'avère que j'avais deux tables avec le même nom.

Sahan Jayasumana
la source
La même chose m'est arrivée d'une manière ou d'une autre: MySQL Workbench n'a montré qu'une seule table `` utilisateur '', cependant, après avoir supprimé toutes les tables de la base de données, il a soudainement montré une autre table `` utilisateur '' qui n'était pas visible auparavant ...
SND
3

Une autre suggestion consiste à vérifier que vous utilisez un type valide pour le champ généré automatiquement. N'oubliez pas que cela ne fonctionne pas avec String, mais cela fonctionne avec Long:

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

@Constraints.Required
public String contents;

La syntaxe ci-dessus a fonctionné pour générer des tables dans MySQL en utilisant Hibernate en tant que fournisseur JPA 2.0.

nize
la source
Changer String en Long a corrigé cela pour moi. Merci
jlars62
3

J'ai eu le même problème. J'ai trouvé le tutoriel Exemple de mappage One-To-One Hibernate utilisant l'annotation de clé étrangère et je l'ai suivi étape par étape comme ci-dessous:

Créez une table de base de données avec ce script:

create table ADDRESS (
   id INT(11) NOT NULL AUTO_INCREMENT,
   street VARCHAR(250) NOT NULL,
   city  VARCHAR(100) NOT NULL,
   country  VARCHAR(100) NOT NULL,
   PRIMARY KEY (id)
);

create table STUDENT (
    id            INT(11) NOT NULL AUTO_INCREMENT, 
    name          VARCHAR(100) NOT NULL, 
    entering_date DATE NOT NULL, 
    nationality   TEXT NOT NULL, 
    code          VARCHAR(30) NOT NULL,
    address_id INT(11) NOT NULL,
    PRIMARY KEY (id),
    CONSTRAINT student_address FOREIGN KEY (address_id) REFERENCES ADDRESS (id)   
);

Voici les entités avec les tableaux ci-dessus

@Entity
@Table(name = "STUDENT")
public class Student implements Serializable {

    private static final long serialVersionUID = 6832006422622219737L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

 }

@Entity
@Table(name = "ADDRESS")
public class Address {

    @Id @GeneratedValue
    @Column(name = "ID")
    private long id;
}

Le problème a été résolu.

Remarque: la clé primaire doit être définie sur AUTO_INCREMENT

David Pham
la source
2

Ajoutez simplement une contrainte non nulle

J'ai eu le même problème. Je viens d'ajouter une contrainte non nulle dans le mappage xml. Ça a marché

<set name="phone" cascade="all" lazy="false" > 
   <key column="id" not-null="true" />
   <one-to-many class="com.practice.phone"/>
</set>
user2982704
la source
2

C'est peut-être le problème avec le schéma de table. supprimez la table et réexécutez l'application.

SHIVA
la source
1

En plus de ce qui est mentionné ci-dessus, n'oubliez pas lors de la création de la table sql de faire l' incrémentation automatique comme dans cet exemple

CREATE TABLE MY_SQL_TABLE (

  USER_ID INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
  FNAME VARCHAR(50) NOT NULL,
  LNAME VARCHAR(20) NOT NULL,
  EMAIL VARCHAR(50) NOT NULL
);
Ahmad Merghany
la source
0

Veuillez vérifier si la valeur par défaut de l'ID de colonne dans une table particulière. Si elle n'est pas définie par défaut

Arun
la source
0

J'ai eu le même problème. J'utilisais une table de jointure et tout ce que j'avais avec un champ d'identification de ligne et deux clés étrangères. Je ne connais pas la cause exacte mais j'ai fait ce qui suit

  1. Mise à niveau de MySQL vers la communauté 5.5.13
  2. Renommez la classe et la table
  3. Assurez-vous d'avoir des méthodes de hashcode et d'égalité

    @Entity 
    @Table(name = "USERGROUP")
    public class UserGroupBean implements Serializable {
    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name = "USERGROUP_ID")
    private Long usergroup_id;
    
    @Column(name = "USER_ID")   
    private Long user_id;
    
    @Column(name = "GROUP_ID")
    private Long group_id;
Eric
la source
0

La même exception était levée si une table DB avait une ancienne colonne non supprimée.

Par exemple: attribute_id NOT NULL BIGINT(20),etattributeId NOT NULL BIGINT(20),

Après avoir supprimé l'attribut non utilisé, dans mon cas contractId , le problème a été résolu.

Viktor Reinok
la source
0

Cela m'est arrivé avec une @ManyToManyrelation. J'avais annoté l'un des champs de la relation avec @JoinTable, je l'ai supprimé et j'ai utilisé l' mappedByattribut sur @ManyToMany à la place.

Gary69
la source
Pouvez vous donner un exemple?
Malena T
0

J'ai essayé le code et dans mon cas, le code ci-dessous résout le problème. Je n'avais pas réglé le schéma correctement

@Entity
    @Table(name="table"
         ,catalog="databasename"
      )

Veuillez essayer d'ajouter ,catalog="databasename" la même chose que moi.

,catalog="databasename"
Justo Miguel
la source
0

Dans mon cas, j'ai modifié les tables incriminées et le champ "id" en question je l'ai fait AUTO_INCREMENT, j'ai encore besoin de comprendre pourquoi au moment du déploiement il ne le faisait pas "AUTO_INCREMENT" pour que je doive le faire moi-même!

Ishimwe Aubain Consolateur
la source
0

Et ça:

<set name="fieldName" cascade="all"> 
   <key column="id" not-null="true" />
   <one-to-many class="com.yourClass"/>
</set>

J'espère que ça t'aide.

David Davila
la source
0

Essayez de changer le Longtype d'objet en type longprimitif (si l'utilisation de primitives vous convient).

J'ai eu le même problème et le changement de type m'a aidé.

Olga
la source
0

J'ai eu ce problème, par erreur j'avais placé une @Transientannotation au-dessus de cet attribut particulier. Dans mon cas, cette erreur a du sens.

utilisateur158
la source
0

"Le champ 'id' n'a pas de valeur par défaut" car vous ne l'avez pas déclaré GenerationType.IDENTITYdans GeneratedValueAnnotation.

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
Dracula Oppa
la source
0

Ce problème est dû au fait que parfois vous devez à nouveau mettre à jour / créer la base de données ou parfois si vous avez ajouté le champ dans la table de base de données mais pas dans la classe d'entité, il ne peut pas insérer de valeur nulle ou zéro, donc cette erreur est survenue. Vérifiez donc les classes side.Db et Entity.

Shubham
la source
0

Lorsque votre champ n'est pas nullable, une valeur par défaut doit être spécifiée lors de la création de la table. Recréez une table avec AUTO_INCREMENT correctement initialisé afin que DB ne nécessite pas de valeur par défaut car il la générera par lui-même et n'y mettra jamais NULL.

CREATE TABLE Persons (
Personid int NOT NULL AUTO_INCREMENT,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Age int,
PRIMARY KEY (Personid)

);

https://www.w3schools.com/sql/sql_autoincrement.asp

Anatoly Leonov
la source
0

J'ai une telle erreur dans GCP cloud sql lorsque le champ de modèle ne correspond pas au champ de table correct dans la base de données. Exemple: quand dans le champ de modèle, la fieldName
table dans la base de données devrait avoir le champ La field_name correction du nom du champ de la table m'a aidé.

jhenya-d
la source
-1

Ajoutez une méthode hashCode()à votre classe Entity Bean et réessayez

tarhack
la source
pourriez-vous expliquer pourquoi?
Raja Anbazhagan