Hibernate: "El campo 'id' no tiene un valor predeterminado"

130

Me enfrento a lo que creo que es un problema simple con Hibernate, pero no puedo resolverlo (los foros de Hibernate que son inalcanzables ciertamente no ayudan).

Tengo una clase simple que me gustaría persistir, pero sigo obteniendo:

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 ]

El código relevante para la clase persistente es:

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;
    }
}

Y el código de ejecución real es simple:

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();
}

Intenté algunas "estrategias" dentro de la GeneratedValueanotación, pero parece que no funciona. ¡Inicializar idtampoco ayuda! (por ejemplo Long id = 20L)

¿Alguien podría arrojar algo de luz?

EDIT 2: confirmado: jugar con @GeneratedValue(strategy = GenerationType.XXX)no lo resuelve

SOLUCIONADO: recrear la base de datos resolvió el problema

André Chalella
fuente
¿Cuál es la fuente del constructor que usa String?
Michael Pralow
Lo siento, lo omití. Simplemente inicializa un campo de cadena con el valor pasado.
André Chalella el
1
¿Cómo está generando las ID en el lado de la base de datos?
James McMahon el
55
GRACIAS ! Nunca pensé en recrear la base de datos cuando era necesario cambiar las estrategias. :-)
Jan Goyvaerts
1
He cambiado GenerationTypeen @GeneratedValuea partir IDENTITYde AUTOy funcionó para mí. Además, puede tener la propiedad de incremento automático establecida en MySQL.
Vishrant

Respuestas:

113

A veces, los cambios realizados en el modelo o en el ORM pueden no reflejarse con precisión en la base de datos incluso después de una ejecución de SchemaUpdate .

Si el error realmente parece carecer de una explicación sensata, intente recrear la base de datos (o al menos crear una nueva) y andamiarla con ella SchemaExport.

André Chalella
fuente
13
En muchos casos, este problema también se puede resolver simplemente soltando la tabla o tablas infractoras, suponiendo que Hibernate esté configurado para crear / administrar automáticamente el esquema de base de datos. Para soltar tablas de un esquema administrado, SET foreign_key_checks = 0;es tu amigo. Solo asegúrate SET foreign_key_checks = 1;cuando hayas terminado.
Aroth
Tengo el mismo problema e intento con su ans pero nuevamente recibí el mismo error, qué error hago, no sé ... Estoy usando la base de datos mysql.
Krunal Patel
56

Si desea que MySQL produzca claves primarias automáticamente, debe indicarlo al crear la tabla. No tienes que hacer esto en Oracle.

En la clave principal debe incluir AUTO_INCREMENT. Vea el ejemplo a continuación.

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;  

Aquí está la entidad

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
fuente
13

debe estar utilizando la actualización en su propiedad hbm2ddl. realice los cambios y actualícelo a Crear para que pueda crear la tabla.

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

Funcionó para mi.

anzie001
fuente
1
Es trabajo para mi. Hibernate + Derby DB @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; Y con el valor createen la hbm2ddl.autopropiedad los cambios aplicados en mi Esquema de base de datos. Muchas gracias ...
Adam M. Gamboa G.
12

Echa un vistazo a GeneratedValuela estrategia. Por lo general, se parece a:

@GeneratedValue(strategy=GenerationType.IDENTITY)
Steve Kuo
fuente
Solo voy a sugerir esto, intente usar esto en lugar de .AUTO.
James McMahon el
Tengo que revisarlo mañana, pero estoy casi seguro de que eso no lo solucionará. Veo muchas claves de ID usando GenerationType.AUTO. De todos modos, me aseguraré de probarlo mañana.
André Chalella el
Confirmado - no ayuda
André Chalella
6

Dejar la tabla de la base de datos manualmente y luego volver a ejecutar la aplicación funcionó para mí. En mi caso, la tabla no se creó correctamente (con restricciones), supongo.

Sen
fuente
Gran solución No pensé de esa manera. Gracias
Meir
Deberíamos hacer esto cuando hagamos algún cambio en la columna Id o en el tipo Generación
Jadda
5

Tuve este problema Mi error fue establecer los archivos insertables y actualizables como falsos e intentaba establecer el campo en la solicitud. Este campo se establece como NO NULL en DB.

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

Más tarde lo cambié a: insertable = verdadero, actualizable = verdadero

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

Funcionó perfectamente más tarde.

Kavitha yadav
fuente
actualizable es verdadero por defecto
Janac Meena
4

Vine aquí debido al mensaje de error, resulta que tenía dos tablas con el mismo nombre.

Sahan Jayasumana
fuente
De alguna manera me sucedió lo mismo: MySQL workbench mostró solo una tabla de 'usuario', sin embargo, después de que eliminé todas las tablas de la base de datos, de repente mostró otra tabla de 'usuario' que no era visible antes ...
SND
3

Otra sugerencia es verificar que use un tipo válido para el campo generado automáticamente. Recuerde que no funciona con String, pero funciona con Long:

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

@Constraints.Required
public String contents;

La sintaxis anterior funcionó para generar tablas en MySQL usando Hibernate como proveedor de JPA 2.0.

nize
fuente
Cambiar String a Long me arregló esto. Gracias
jlars62
3

Yo tuve el mismo problema. Encontré el tutorial Ejemplo de mapeo uno a uno de Hibernate usando Anotación de clave externa y lo seguí paso a paso como a continuación:

Cree una tabla de base de datos con este 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)   
);

Aquí están las entidades con las tablas anteriores.

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

El problema fue resuelto.

Aviso: la clave principal debe establecerse en AUTO_INCREMENT

David Pham
fuente
2

Simplemente agregue una restricción no nula

Yo tuve el mismo problema. Acabo de agregar una restricción no nula en el mapeo xml. Funcionó

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

Tal vez ese sea el problema con el esquema de la tabla. suelte la tabla y vuelva a ejecutar la aplicación.

SHIVA
fuente
1

Además de lo mencionado anteriormente, no olvides al crear la tabla sql para hacer el INCREMENTO AUTOMÁTICO como en este ejemplo

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
fuente
0

Compruebe si el valor predeterminado para el ID de columna en la tabla en particular, si no lo establece como predeterminado

Arun
fuente
0

Yo tuve el mismo problema. Estaba usando una tabla de unión y todo lo que tenía con un campo de id de fila y dos claves foráneas. No sé la causa exacta pero hice lo siguiente

  1. MySQL actualizado a la comunidad 5.5.13
  2. Cambiar el nombre de la clase y la tabla
  3. Asegúrate de tener códigos hash e iguales

    @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
fuente
0

Se produjo la misma excepción si una tabla de base de datos tenía una columna antigua no eliminada.

Por ejemplo: attribute_id NOT NULL BIGINT(20),yattributeId NOT NULL BIGINT(20),

Después de eliminar el atributo no utilizado, en mi caso contractId , el problema se resolvió.

Viktor Reinok
fuente
0

Esto me pasó con una @ManyToManyrelación. Había anotado uno de los campos en la relación @JoinTable, lo mappedByeliminé y usé el atributo en @ManyToMany en su lugar.

gary69
fuente
¿Puede dar un ejemplo?
Malena T
0

Probé el código y, en mi caso, el siguiente código resuelve el problema. No había resuelto el esquema correctamente

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

Intenta agregar ,catalog="databasename" lo mismo que hice.

,catalog="databasename"
Justo Miguel
fuente
0

En mi caso, modifiqué las tablas ofensivas y el campo "id" en cuestión. Lo hice AUTO_INCREMENT, todavía necesito descubrir por qué en el momento del despliegue no lo estaba haciendo "AUTO_INCREMENT" ¡así que tengo que hacerlo solo!

Ishimwe Aubain Consolateur
fuente
0

¿Qué hay de esto?

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

Espero que te ayude.

David Dávila
fuente
0

Intente cambiar el Longtipo de objeto a tipo longprimitivo (si usar primitivas está bien para usted).

Tuve el mismo problema y cambiar de tipo me ayudó.

Olga
fuente
0

Tuve este problema, por error puse una @Transientanotación sobre ese atributo en particular. En mi caso este error tiene sentido.

usuario158
fuente
0

"El campo 'id' no tiene un valor predeterminado" porque no declaró GenerationType.IDENTITYen GeneratedValueAnotación.

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

Este problema se debe a que a veces necesita actualizar / crear nuevamente la base de datos o, a veces, si ha agregado el campo en la tabla db pero no en la clase de entidad, entonces no puede insertar ningún valor nulo o cero, por lo que se produjo este error. Así que verifique ambos lados. Clase DB y Entidad.

Shubham
fuente
0

Cuando su campo no es anulable, requiere que se especifique un valor predeterminado en la creación de la tabla. Recree una tabla con AUTO_INCREMENT correctamente inicializada para que DB no requiera un valor predeterminado ya que lo generará por sí mismo y nunca pondrá NULL allí.

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
fuente
0

Tengo ese error en la nube GCP sql cuando el campo del modelo no coincide con el campo de tabla correcto en db. Ejemplo: cuando en el campo modelo hay una fieldName
tabla en db, debería tener un campo field_name .

jhenya-d
fuente
-1

Agregue un método hashCode()a su clase de Bean de entidad y vuelva a intentarlo

Tarhack
fuente
¿podría explicar por qué?
Raja Anbazhagan