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

André Chalella
źródło
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.

André Chalella
źródło
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;
  }

}
Greg Keyes
źródło
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.

anzie001
źródł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)
Steve Kuo
źródło
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).

Sen
źródło
Ś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.

Kavitha yadav
źródło
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.

Sahan Jayasumana
źródło
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.

nize
źródło
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

David Pham
źródło
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>
user2982704
źródło
2

Może to jest problem ze schematem tabeli. upuść tabelę i ponownie uruchom aplikację.

SIEDMIODNIOWA ŻAŁOBA
źródło
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
);
Ahmad Merghany
źródło
0

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

Bieg
źródło
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;
    
Eric
źródło
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.

Viktor Reinok
źródło
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.

gary69
źródło
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"
Justo Miguel
źródło
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!

Ishimwe Aubain Consolateur
źródło
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.

David Davila
źródło
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.

Olga
źródło
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.

user158
źródło
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;
Dracula Oppa
źródło
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.

Shubham
źródło
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

Anatolij Leonow
źródło
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.

jhenya-d
źródło
-1

Dodaj metodę hashCode()do klasy Entity Bean i spróbuj ponownie

Tarhack
źródło
czy mógłbyś wyjaśnić dlaczego?
Raja Anbazhagan