ไฮเบอร์เนต:“ ฟิลด์ 'id' ไม่มีค่าเริ่มต้น”


130

ฉันกำลังเผชิญกับสิ่งที่ฉันคิดว่าเป็นปัญหาง่ายๆกับ Hibernate แต่ไม่สามารถแก้ไขได้ (ฟอรัม Hibernate ไม่สามารถเข้าถึงได้อย่างแน่นอนไม่ช่วยอะไร)

ฉันมีคลาสง่ายๆที่ฉันอยากจะเรียนต่อ แต่ได้รับ:

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 ]

รหัสที่เกี่ยวข้องสำหรับคลาสที่คงอยู่คือ:

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

และรหัสที่ใช้งานจริงเป็นเพียงธรรมดา:

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

ฉันลองใช้ "กลยุทธ์" บางอย่างภายในGeneratedValueคำอธิบายประกอบ แต่ดูเหมือนจะไม่ได้ผล การเริ่มต้นidก็ไม่ช่วยเช่นกัน! (เช่นLong id = 20L).

ใครช่วยส่องแสงบ้าง

แก้ไข 2:ยืนยัน: การยุ่งกับ@GeneratedValue(strategy = GenerationType.XXX)ไม่สามารถแก้ปัญหาได้

แก้ไขแล้ว: การสร้างฐานข้อมูลใหม่ช่วยแก้ปัญหาได้


แหล่งที่มาของ Constructor โดยใช้ String คืออะไร?
Michael Pralow

ขออภัยฉันมองข้ามสิ่งนั้นไป เริ่มต้นฟิลด์สตริงด้วยค่าที่ผ่าน
André Chalella

1
คุณสร้าง ID บนฐานข้อมูลอย่างไร?
James McMahon

5
ขอบคุณ ! ไม่เคยคิดว่าจะต้องสร้างฐานข้อมูลใหม่เมื่อเปลี่ยนกลยุทธ์ :-)
Jan Goyvaerts

1
ผมเปลี่ยนGenerationTypeใน@GeneratedValueจากIDENTITYไปAUTOและมันทำงานให้ฉัน นอกจากนี้คุณสามารถตั้งค่าคุณสมบัติการเพิ่มอัตโนมัติใน MySQL
Vishrant

คำตอบ:


113

บางครั้งการเปลี่ยนแปลงที่เกิดขึ้นกับแบบจำลองหรือ ORM อาจไม่สะท้อนถึงฐานข้อมูลอย่างถูกต้องแม้ว่าจะมีการดำเนินการแล้วก็ตาม SchemaUpdateแล้วก็ตาม

หากมีข้อผิดจริงดูเหมือนว่าจะขาดคำอธิบายที่สมเหตุสมผลพยายามสร้างฐานข้อมูล (หรืออย่างน้อยก็สร้างใหม่) SchemaExportและนั่งร้านด้วย


13
ในหลาย ๆ กรณีปัญหานี้สามารถแก้ไขได้โดยเพียงแค่ทิ้งตาราง (หรือตาราง) ที่กระทำผิดโดยสมมติว่า Hibernate ถูกตั้งค่าให้สร้าง / จัดการสคีมา DB โดยอัตโนมัติ หากต้องการวางตารางจากสคีมาที่มีการจัดการSET foreign_key_checks = 0;คือเพื่อนของคุณ อย่าลืมว่าSET foreign_key_checks = 1;เมื่อคุณทำเสร็จแล้ว
aroth

ฉันพบปัญหาเดียวกันและลองใช้ ans ของคุณ แต่มีข้อผิดพลาดเดียวกันอีกครั้งฉันทำผิดอะไรฉันไม่รู้ ...... ฉันใช้ฐานข้อมูล mysql
Krunal Patel

56

หากคุณต้องการให้ MySQL สร้างคีย์หลักโดยอัตโนมัติคุณต้องบอกเมื่อสร้างตาราง คุณไม่จำเป็นต้องทำสิ่งนี้ใน Oracle

AUTO_INCREMENTในหลักสำคัญที่คุณต้องรวมถึง ดูตัวอย่างด้านล่าง

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;  

นี่คือเอนทิตี

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

คุณต้องใช้การอัปเดตในคุณสมบัติ hbm2ddl ของคุณ ทำการเปลี่ยนแปลงและอัปเดตเป็นสร้างเพื่อให้สามารถสร้างตารางได้

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

มันได้ผลสำหรับฉัน


1
มันทำงานสำหรับฉัน Hibernate + Derby DB @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; และด้วยค่าcreateในhbm2ddl.autoคุณสมบัติการเปลี่ยนแปลงที่ใช้ในสคีมาฐานข้อมูลของฉัน ขอบคุณมาก ....
Adam M. Gamboa G.

12

ลองดูGeneratedValueกลยุทธ์ของ โดยทั่วไปจะมีลักษณะดังนี้:

@GeneratedValue(strategy=GenerationType.IDENTITY)

กำลังจะแนะนำสิ่งนี้ให้ลองใช้สิ่งนี้แทน. AUTO
James McMahon

ฉันต้องตรวจสอบในวันพรุ่งนี้ แต่ฉันเกือบจะแน่ใจว่าจะไม่แก้ไข ฉันเห็นรหัส ID จำนวนมากที่ใช้ GenerationType.AUTO อย่างไรก็ตามฉันจะทดสอบในวันพรุ่งนี้
André Chalella

ยืนยัน - ไม่ช่วย
André Chalella

6

การลบตารางออกจากฐานข้อมูลด้วยตนเองแล้วเรียกใช้แอปพลิเคชันอีกครั้งได้ผลสำหรับฉัน ในตารางกรณีของฉันไม่ได้สร้างขึ้นอย่างถูกต้อง (ด้วยข้อ จำกัด ) ฉันเดา


ทางออกที่ดี ไม่ได้คิดแบบนั้น. ขอบคุณ
Meir

เราควรทำสิ่งนี้เมื่อเราทำการเปลี่ยนแปลงคอลัมน์ Id หรือประเภทการสร้าง
Jadda

5

ฉันมีปัญหานี้ ความผิดพลาดของฉันคือฉันตั้งค่าไฟล์ที่แทรกและอัพเดตได้เป็นเท็จและพยายามตั้งค่าฟิลด์ในคำขอ ฟิลด์นี้ถูกตั้งค่าเป็น NON NULL ใน DB

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

ต่อมาฉันเปลี่ยนเป็น - insertable = true, updatable = true

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

มันทำงานได้อย่างสมบูรณ์ในภายหลัง


อัปเดตได้เป็นจริงตามค่าเริ่มต้น
Janac Meena

4

ฉันมาที่นี่เพราะข้อความแสดงข้อผิดพลาดปรากฎว่าฉันมีสองตารางที่มีชื่อเดียวกัน


สิ่งเดียวกันที่เกิดขึ้นกับฉัน: โต๊ะทำงาน MySQL แสดงตาราง 'ผู้ใช้' เพียงตารางเดียวอย่างไรก็ตามหลังจากที่ฉันทิ้งตารางทั้งหมดในฐานข้อมูลมันก็แสดงตาราง 'ผู้ใช้' อื่นที่ไม่สามารถมองเห็นได้มาก่อน ...
SND

3

คำแนะนำอีกประการหนึ่งคือตรวจสอบว่าคุณใช้ประเภทที่ถูกต้องสำหรับช่องที่สร้างขึ้นโดยอัตโนมัติ จำไว้ว่ามันใช้ไม่ได้กับ String แต่ใช้ได้กับ Long:

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

@Constraints.Required
public String contents;

ไวยากรณ์ข้างต้นใช้สำหรับสร้างตารางใน MySQL โดยใช้ Hibernate เป็นผู้ให้บริการ JPA 2.0


การเปลี่ยน String เป็น Long แก้ไขสิ่งนี้ให้ฉัน ขอบคุณ
jlars62

3

ผมมีปัญหาเหมือนกัน. ฉันพบบทช่วยสอนHibernate One-to-One Mapping Example โดยใช้ Foreign key Annotationและทำตามทีละขั้นตอนดังนี้:

สร้างตารางฐานข้อมูลด้วยสคริปต์นี้:

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

นี่คือเอนทิตีที่มีตารางด้านบน

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

ปัญหาได้รับการแก้ไข

หมายเหตุ: ต้องตั้งค่าคีย์หลักเป็น AUTO_INCREMENT


2

เพียงเพิ่มข้อ จำกัด ที่ไม่เป็นค่าว่าง

ผมมีปัญหาเหมือนกัน. ฉันเพิ่งเพิ่มข้อ จำกัด ที่ไม่ใช่ศูนย์ในการแมป xml มันได้ผล

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

2

นั่นอาจเป็นปัญหากับสคีมาของตาราง วางตารางและเรียกใช้แอปพลิเคชันอีกครั้ง


1

นอกเหนือจากที่กล่าวไว้ข้างต้นอย่าลืมขณะสร้างตาราง sql เพื่อสร้างAUTO INCREMENTดังในตัวอย่างนี้

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

โปรดตรวจสอบว่าค่าดีฟอลต์สำหรับรหัสคอลัมน์ในตารางเฉพาะหรือไม่หากไม่ทำให้เป็นค่าเริ่มต้น


0

ผมมีปัญหาเหมือนกัน. ฉันใช้ตารางการเข้าร่วมและทั้งหมดที่ฉันมีคือฟิลด์ id แถวและคีย์ต่างประเทศสองอัน ฉันไม่ทราบสาเหตุที่แท้จริง แต่ฉันทำสิ่งต่อไปนี้

  1. อัปเกรด MySQL เป็นชุมชน 5.5.13
  2. เปลี่ยนชื่อชั้นเรียนและตาราง
  3. ตรวจสอบว่าฉันมีแฮชโค้ดและเท่ากับเมธอด

    @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

ข้อยกเว้นเดียวกันนี้เกิดขึ้นหากตาราง DB มีคอลัมน์เก่าที่ยังไม่ถูกลบออก

ตัวอย่างเช่น: attribute_id NOT NULL BIGINT(20),และattributeId NOT NULL BIGINT(20),

หลังจากลบแอตทริบิวต์ not used ในกรณีของฉันcontractIdปัญหาได้รับการแก้ไข


0

สิ่งนี้เกิดขึ้นกับฉันด้วย@ManyToManyความสัมพันธ์ ฉันใส่คำอธิบายประกอบลงในฟิลด์หนึ่งในความสัมพันธ์@JoinTableฉันลบข้อมูลนั้นออกและใช้mappedByแอตทริบิวต์บน @ManyToMany แทน


คุณสามารถให้ตัวอย่างได้หรือไม่?
Malena T

0

ฉันลองใช้รหัสแล้วและในกรณีของฉันรหัสด้านล่างช่วยแก้ปัญหาได้ ฉันไม่ได้ตัดสินสคีมาอย่างถูกต้อง

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

โปรดลองเพิ่ม ,catalog="databasename" แบบเดียวกับที่ฉันทำ

,catalog="databasename"

0

ในกรณีของฉันฉันแก้ไขตารางที่กระทำผิดและ "id" ที่เป็นปัญหาซึ่งฉันทำให้เป็น AUTO_INCREMENT ฉันยังคงต้องหาสาเหตุว่าทำไมเวลาปรับใช้จึงไม่ทำให้เป็น "AUTO_INCREMENT" ดังนั้นฉันจึงต้องทำด้วยตัวเอง!



0

ลองเปลี่ยนLongประเภทวัตถุเป็นlongดั้งเดิม (ถ้าคุณใช้แบบดั้งเดิมก็โอเคสำหรับคุณ)

ฉันมีปัญหาเดียวกันและการเปลี่ยนประเภทช่วยฉันได้


0

ฉันประสบปัญหานี้โดยไม่ได้ตั้งใจฉันได้วาง@Transientคำอธิบายประกอบไว้เหนือแอตทริบิวต์นั้น ๆ ในกรณีของฉันข้อผิดพลาดนี้สมเหตุสมผล



0

ปัญหานี้เป็นเพราะบางครั้งคุณต้องอัปเดต / สร้างฐานข้อมูลอีกครั้งหรือบางครั้งถ้าคุณเพิ่มฟิลด์ในตาราง db แต่ไม่ใช่คลาสเอนทิตีก็จะไม่สามารถแทรกค่าว่างหรือศูนย์ใด ๆ ได้ดังนั้นข้อผิดพลาดนี้จึงเกิดขึ้น ดังนั้นตรวจสอบทั้ง side.Db และ Entity class


0

เมื่อเขตข้อมูลของคุณไม่สามารถว่างได้จำเป็นต้องมีการระบุค่าเริ่มต้นในการสร้างตาราง สร้างตารางใหม่ด้วย AUTO_INCREMENT ที่เริ่มต้นอย่างถูกต้องดังนั้น DB จะไม่ต้องการค่าดีฟอลต์เนื่องจากจะสร้างตารางขึ้นมาเองและไม่ใส่ 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

ฉันมีข้อผิดพลาดดังกล่าวใน GCP cloud sql เมื่อฟิลด์โมเดลไม่ตรงกับฟิลด์ตารางที่ถูกต้องใน db ตัวอย่าง: เมื่ออยู่ในฟิลด์ model เป็นfieldName
ตารางใน db ควรมีฟิลด์field_name Fixing table ชื่อฟิลด์ช่วยฉัน


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.