Hibernate: „Pole 'id' nie ma wartości domyślnej”


131

Mam do czynienia z prostym problemem związanym z Hibernacją, ale nie mogę go rozwiązać (niedostępność forów Hibernate z pewnością nie pomaga).

Mam prostą klasę, którą chciałbym wytrwać, ale wciąż otrzymuję:

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 ]

Odpowiedni kod dla utrwalonej klasy to:

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

A rzeczywisty działający kod jest po prostu prosty:

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

Wypróbowałem kilka „strategii” w GeneratedValueadnotacji, ale to po prostu nie działa. Inicjalizacja idteż nie pomaga! (np Long id = 20L.).

Czy ktoś mógłby rzucić trochę światła?

EDYCJA 2: potwierdzona: mieszanie się z nim @GeneratedValue(strategy = GenerationType.XXX)nie rozwiązuje problemu

ROZWIĄZANE: odtworzenie bazy danych rozwiązało problem


Jakie jest źródło konstruktora używającego String?
— Michael Pralow

Przepraszam, pominąłem to. Po prostu inicjalizuje pole typu String z przekazaną wartością.
— André Chalella,

1
Jak generujesz identyfikatory po stronie bazy danych?
— James McMahon

5
DZIĘKI ! Podczas zmiany strategii nigdy nie myśleliśmy o odtworzeniu bazy danych. :-)
— Jan Goyvaerts

1
Zmieniłem GenerationTypesię @GeneratedValueod IDENTITYcelu AUTOi pracował dla mnie. Możesz również ustawić właściwość automatycznego zwiększania wartości w MySQL.
— Vishrant

Odpowiedzi:


113

Czasami zmiany wprowadzone w modelu lub w ORM mogą nie odzwierciedlać dokładnie w bazie danych nawet po wykonaniu SchemaUpdate.

Jeśli błąd faktycznie wydaje się nie mieć sensownego wyjaśnienia, spróbuj odtworzyć bazę danych (lub przynajmniej utworzyć nową) i zbudować ją za pomocą SchemaExport.


13
W wielu przypadkach ten problem można również rozwiązać, po prostu upuszczając nieprawidłową tabelę (lub tabele), zakładając, że Hibernate jest skonfigurowany do automatycznego tworzenia / zarządzania schematem bazy danych. Aby usunąć tabele z zarządzanego schematu, SET foreign_key_checks = 0;jest twoim przyjacielem. Po prostu pamiętaj, SET foreign_key_checks = 1;kiedy skończysz.
— aroth

Mam ten sam problem i spróbuję z twoimi odpowiedziami, ale znowu mam ten sam błąd jaki błąd robię nie wiem ...... Używam bazy danych mysql.
— Krunal Patel

59

Jeśli chcesz, aby MySQL automatycznie tworzył klucze podstawowe, musisz to powiedzieć podczas tworzenia tabeli. Nie musisz tego robić w Oracle.

Na kluczu podstawowym musisz podać AUTO_INCREMENT. Zobacz poniższy przykład.

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;  

Oto Jednostka

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

}

13

musisz używać aktualizacji w swojej właściwości hbm2ddl. wprowadź zmiany i zaktualizuj go, aby utworzyć, aby mógł utworzyć tabelę.

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

U mnie to zadziałało.


1
To dla mnie praca. Hibernate + Derby DB @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; A z wartością createwe hbm2ddl.autowłaściwości zmiany zastosowane w moim schemacie bazy danych. Wielkie dzięki ....
— Adam M. Gamboa G.

12

Spójrz na GeneratedValuestrategię firmy. Zazwyczaj wygląda to tak:

@GeneratedValue(strategy=GenerationType.IDENTITY)

Mam zamiar to zasugerować, spróbuj użyć tego zamiast .AUTO.
— James McMahon

Muszę to sprawdzić jutro, ale jestem prawie pewien, że to nie pomoże. Widzę wiele kluczy ID używających GenerationType.AUTO. Tak czy inaczej, jutro na pewno to przetestuję.
— André Chalella,

Potwierdzony - nie pomaga
— André Chalella

6

Ręczne usunięcie tabeli z bazy danych i ponowne uruchomienie aplikacji zadziałało. W moim przypadku tabela nie została utworzona poprawnie (z ograniczeniami).


Świetne rozwiązanie. Nie myślałem w ten sposób. Dzięki
— Meir

Powinniśmy to zrobić, gdy wprowadzimy jakiekolwiek zmiany w kolumnie Id lub typie generacji
— Pavan Jadda

6

Miałem ten problem. Mój błąd polegał na tym, że ustawiłem pola do wstawienia i aktualizowalne jako fałszywe i próbowałem ustawić pole w żądaniu. To pole jest ustawione jako NON NULL w DB.

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

Później zmieniłem to na - insertable = true, updatable = true

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

Później zadziałało doskonale.


możliwość aktualizacji jest domyślnie prawdziwe
— Janac Meena

4

Przyjechałem tu z powodu komunikatu o błędzie, okazuje się, że miałem dwie tabele o tej samej nazwie.


To samo w jakiś sposób mi się przytrafiło: Środowisko pracy MySQL pokazało tylko jedną tabelę „użytkownika”, jednak po usunięciu wszystkich tabel z bazy danych nagle pokazał kolejną tabelę „użytkownika”, która nie była wcześniej widoczna ...
— SND

3

Inną sugestią jest sprawdzenie, czy używasz prawidłowego typu dla pola generowanego automatycznie. Pamiętaj, że nie działa z String, ale działa z Long:

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

@Constraints.Required
public String contents;

Powyższa składnia działała przy generowaniu tabel w MySQL przy użyciu Hibernate jako dostawcy JPA 2.0.


Zmiana String na Long naprawiła to dla mnie. Dzięki
— jlars62

3

Miałem ten sam problem. Znalazłem samouczek Hibernate One-To-One Mapping Example using Foreign key Adnotation i postępowałem zgodnie z nim krok po kroku, jak poniżej:

Utwórz tabelę bazy danych za pomocą tego skryptu:

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

Oto jednostki z powyższymi tabelami

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

Problem został rozwiązany.

Uwaga: klucz podstawowy musi być ustawiony na AUTO_INCREMENT


2

Po prostu dodaj ograniczenie niezerowe

Miałem ten sam problem. Właśnie dodałem ograniczenie niezerowe w mapowaniu XML. Zadziałało

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


1

Oprócz tego, co zostało wspomniane powyżej, nie zapomnij podczas tworzenia tabeli sql, aby wykonać AUTO INCREMENT, jak w tym przykładzie

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

0

Sprawdź, czy wartość domyślna dla identyfikatora kolumny w konkretnej tabeli. Jeśli nie ustawia jej jako domyślnej


0

Miałem ten sam problem. Używałem tabeli łączenia i wszystkiego, co miałem z polem id wiersza i dwoma kluczami obcymi. Nie znam dokładnej przyczyny, ale wykonałem następujące czynności

  1. Uaktualniono MySQL do społeczności 5.5.13
  2. Zmień nazwę klasy i tabeli
  3. Upewnij się, że mam metody hashcode i equals

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

0

Ten sam wyjątek został zgłoszony, jeśli tabela DB miała starą nieusuniętą kolumnę.

Na przykład: attribute_id NOT NULL BIGINT(20),iattributeId NOT NULL BIGINT(20),

Po usunięciu atrybutu not used, w moim przypadku contractId , problem został rozwiązany.


0

Przydarzyło mi się to w @ManyToManyzwiązku. Dodałem adnotację do jednego z pól w relacji z @JoinTable, usunąłem to i mappedByzamiast tego użyłem atrybutu na @ManyToMany.


Czy możesz podać przykład?
— Malena T

0

Wypróbowałem kod iw moim przypadku poniższy kod rozwiązuje problem. Nie ustaliłem poprawnie schematu

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

Spróbuj dodać ,catalog="databasename" to samo, co ja.

,catalog="databasename"

0

W moim przypadku zmieniłem tabele naruszające i pole „id”, o którym mowa, zrobiłem to AUTO_INCREMENT, nadal muszę dowiedzieć się, dlaczego w czasie wdrażania nie robiło to „AUTO_INCREMENT”, więc muszę to zrobić sam!


0

A co z tym:

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

Mam nadzieję, że Ci to pomoże.


0

Spróbuj zmienić Longtyp obiektu nalong pierwotny (jeśli używanie prymitywów jest dla ciebie w porządku).

Miałem ten sam problem i pomogła mi zmiana typu.


0

Miałem ten problem, przez pomyłkę umieściłem @Transientadnotację powyżej tego konkretnego atrybutu. W moim przypadku ten błąd ma sens.


0

„Pole„ id ”nie ma wartości domyślnej”, ponieważ nie zostało zadeklarowane GenerationType.IDENTITYw GeneratedValueAdnotacji.

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

0

Ten problem jest spowodowany tym, że czasami trzeba ponownie zaktualizować / utworzyć bazę danych lub czasami, jeśli dodano pole w tabeli db, ale nie klasę jednostki, nie można wstawić żadnej wartości null ani zera, więc pojawił się ten błąd. Sprawdź więc zarówno klasę side.Db, jak i Entity.


0

Gdy pole nie dopuszcza wartości null, wymaga określenia wartości domyślnej podczas tworzenia tabeli. Ponownie utwórz tabelę z prawidłowo zainicjowaną funkcją AUTO_INCREMENT, aby DB nie wymagał wartości domyślnej, ponieważ wygeneruje ją samodzielnie i nigdy nie ustawi tam wartości 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


0

Mam taki błąd w sql w chmurze GCP, gdy pole modelu nie pasuje do prawidłowego pola tabeli w db. Przykład: gdy w polu modelu znajduje się fieldName
tabela w db powinna mieć pole field_name Naprawianie nazwy pola tabeli tabeli pomogło mi.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.