Hibernar: "O campo 'id' não tem um valor padrão"

130

Estou enfrentando o que considero um problema simples com o Hibernate, mas não consigo resolvê-lo (os fóruns do Hibernate inacessíveis certamente não ajudam).

Eu tenho uma classe simples que gostaria de persistir, mas continuo recebendo:

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 ]

O código relevante para a classe persistida é:

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

E o código em execução real é simples:

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

Tentei algumas "estratégias" na GeneratedValueanotação, mas parece que não funciona. A inicialização idtambém não ajuda! (por exemplo Long id = 20L).

Alguém poderia lançar alguma luz?

EDIT 2: confirmado: mexer com @GeneratedValue(strategy = GenerationType.XXX)não resolve

RESOLVIDO: recriar o banco de dados resolveu o problema

André Chalella
fonte
Qual é a fonte do construtor usando String?
Michael Pralow
Desculpe, eu omiti isso. Apenas inicializa um campo String com o valor passado.
André Chalella 30/04/09
1
Como você está gerando os IDs no lado do banco de dados?
James McMahon
5
THX ! Nunca foi necessário recriar o banco de dados ao alterar as estratégias. :-)
Jan Goyvaerts
1
Eu mudei GenerationTypeem @GeneratedValuepartir IDENTITYpara AUTOe funcionou para mim. Além disso, você pode ter a propriedade de incremento automático definida no MySQL.
Vishrant

Respostas:

113

Às vezes, as alterações feitas no modelo ou no ORM podem não refletir com precisão no banco de dados, mesmo após a execução de SchemaUpdate.

Se, na verdade, o erro parece não ter uma explicação sensata, tente recriar o banco de dados (ou pelo menos criar um novo) e faça o andaime com ele SchemaExport.

André Chalella
fonte
13
Em muitos casos, esse problema também pode ser resolvido simplesmente descartando a (s) tabela (s) ofensiva (s), assumindo que o Hibernate esteja configurado para criar / gerenciar automaticamente o esquema do banco de dados. Para eliminar tabelas de um esquema gerenciado, SET foreign_key_checks = 0;é seu amigo. Apenas certifique-se de SET foreign_key_checks = 1;quando terminar.
Aroth 27/08/12
Eu tenho o mesmo problema e tente com o seu ans, mas novamente tenho o mesmo erro que erro eu faço eu não sei ...... eu estou usando o banco de dados mysql.
quer
56

Se você deseja que o MySQL produza chaves primárias automaticamente, é necessário informar ao criar a tabela. Você não precisa fazer isso no Oracle.

Na chave primária, você deve incluir AUTO_INCREMENT. Veja o exemplo abaixo.

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;  

Aqui está a entidade

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

você deve estar usando update em sua propriedade hbm2ddl. faça as alterações e atualize-o para Criar para que possa criar a tabela.

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

Funcionou para mim.

anzie001
fonte
1
É trabalho para mim. Hibernate + Derby DB @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; E com o valor createna hbm2ddl.autopropriedade as alterações aplicadas no meu esquema de banco de dados. Muito obrigado ....
Adam M. Gamboa G.
12

Dê uma olhada na GeneratedValueestratégia de. Normalmente, é algo como:

@GeneratedValue(strategy=GenerationType.IDENTITY)
Steve Kuo
fonte
Apenas sugerindo isso, tente usar isso em vez de .AUTO.
James McMahon
Preciso verificar amanhã, mas tenho quase certeza de que isso não será corrigido. Vejo muitas chaves de identificação usando o GenerationType.AUTO. Enfim, vou me certificar de testá-lo amanhã.
André Chalella 30/04/09
Confirmado - não ajuda
André Chalella
6

Descartar a tabela do banco de dados manualmente e depois executar novamente o aplicativo funcionou para mim. No meu caso, a tabela não foi criada corretamente (com restrições), eu acho.

Sen
fonte
Ótima solução. Não pensava assim. Obrigado
Meir
Devemos fazer isso quando fizermos alterações na coluna Id ou no tipo Generation
Jadda 20/11/18
5

Eu tive esse problema. Meu erro foi que eu tinha definido os arquivos inseríveis e atualizáveis ​​como false e estava tentando definir o campo na solicitação. Este campo é definido como NULL NULL no DB.

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

Mais tarde eu mudei para - insertable = true, atualizável = true

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

Funcionou perfeitamente depois.

Kavitha yadav
fonte
atualizável é verdadeira por padrão
Janac Meena
4

Eu vim aqui por causa da mensagem de erro, acontece que eu tinha duas tabelas com o mesmo nome.

Sahan Jayasumana
fonte
A mesma coisa aconteceu comigo: o MySQL Workbench mostrou apenas uma tabela 'user', no entanto, depois que eu soltei todas as tabelas no banco de dados, de repente ele mostrou outra tabela 'user' que não estava visível antes ...
SND
3

Outra sugestão é verificar se você usa um tipo válido para o campo gerado automaticamente. Lembre-se de que não funciona com String, mas funciona com Long:

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

@Constraints.Required
public String contents;

A sintaxe acima trabalhou para gerar tabelas no MySQL usando o Hibernate como um provedor JPA 2.0.

nize
fonte
Alterar String para Long corrigiu isso para mim. Obrigado
jlars62
3

Eu tive o mesmo problema. Encontrei o tutorial Exemplo de mapeamento individual do Hibernate usando Anotação de chave estrangeira e o segui passo a passo, como abaixo:

Crie uma tabela de banco de dados com 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)   
);

Aqui estão as entidades com as tabelas acima

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

O problema foi resolvido.

Aviso: a chave primária deve ser definida como AUTO_INCREMENT

David Pham
fonte
2

Basta adicionar restrição não nula

Eu tive o mesmo problema. Acabei de adicionar restrição não nula no mapeamento xml. Funcionou

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

Talvez esse seja o problema com o esquema da tabela. solte a tabela e execute novamente o aplicativo.

SHIVA
fonte
1

Além do mencionado acima, não se esqueça de criar a tabela sql para fazer o INCREMENTO AUTOMÁTICO, como neste exemplo

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

Verifique se o valor padrão para o ID da coluna em particular table.if não torná-lo como padrão

Uma corrida
fonte
0

Eu tive o mesmo problema. Eu estava usando uma tabela de junção e tudo o que tinha com um campo de identificação de linha e duas chaves estrangeiras. Não sei exatamente o que foi causado, mas fiz o seguinte

  1. MySQL atualizado para a comunidade 5.5.13
  2. Renomeie a classe e a tabela
  3. Certifique-se de que eu tinha métodos de código de hash e iguais

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

A mesma exceção foi lançada se uma tabela do banco de dados tivesse uma coluna antiga não removida.

Por exemplo: attribute_id NOT NULL BIGINT(20),eattributeId NOT NULL BIGINT(20),

Depois de remover o atributo não usado, no meu caso contractId , o problema foi resolvido.

Viktor Reinok
fonte
0

Isso aconteceu comigo com um @ManyToManyrelacionamento. Anotei um dos campos no relacionamento @JoinTable, removi-o e usei o mappedByatributo em @ManyToMany.

gary69
fonte
você pode dar um exemplo?
Malena T
0

Eu tentei o código e, no meu caso, o código abaixo resolve o problema. Eu não havia resolvido o esquema corretamente

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

Por favor, tente adicionar ,catalog="databasename" o mesmo que eu fiz.

,catalog="databasename"
Justo Miguel
fonte
0

No meu caso, alterei as tabelas incorretas e o campo "id" em questão, criei AUTO_INCREMENT, ainda preciso descobrir por que, no tempo de implantação, não estava tornando "AUTO_INCREMENT" para que eu próprio fizesse isso sozinho!

Ishimwe Aubain Consolateur
fonte
0

Que tal isso:

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

Espero que ajude você.

David Davila
fonte
0

Tente alterar o Longtipo de objeto para longo tipo primitivo (se o uso de primitivas estiver correto para você).

Eu tive o mesmo problema e a mudança de tipo me ajudou.

Olga
fonte
0

Eu tive esse problema, por engano, coloquei a @Transientanotação acima desse atributo específico. No meu caso, esse erro faz sentido.

user158
fonte
0

"O campo 'id' não tem um valor padrão" porque você não declarou GenerationType.IDENTITYna GeneratedValueanotação.

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

Esse problema ocorre porque, algumas vezes, você precisa atualizar / criar novamente o banco de dados ou, algumas vezes, se você adicionou o campo na tabela db, mas não a classe de entidade, não é possível inserir nenhum valor nulo ou zero, de modo que esse erro ocorreu. Portanto, verifique as classes side.Db e Entity.

Shubham
fonte
0

Quando seu campo não é anulável, é necessário que um valor padrão seja especificado na criação da tabela. Recrie uma tabela com AUTO_INCREMENT inicializado corretamente, para que o banco de dados não exija valor padrão, pois ele o gerará por si só e nunca colocará NULL lá.

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

Eu tenho esse erro no GCP cloud sql quando o campo de modelo não corresponde ao campo de tabela correto no banco de dados. Exemplo: quando no campo modelo é fieldName
tabela em db deve ter o campo field_name Fixing table field name me ajudou.

jhenya-d
fonte
-1

Adicione um método hashCode()à sua Entity Bean Class e tente novamente

tarhack
fonte
você poderia explicar por que?
Raja Anbazhagan