休眠:“字段'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)不能解决问题

求助:重新创建数据库解决了问题


使用String的构造方法的来源是什么?
Michael Pralow 09年

抱歉,我省略了。只需使用传递的值初始化String字段即可。
安德烈Chalella

1
您如何在数据库端生成ID?
James McMahon

5
谢谢 !更改策略时,从未考虑过需要重新创建数据库。:-)
Jan Goyvaerts'1

1
我改变GenerationType@GeneratedValueIDENTITYAUTO它为我工作。另外,您可以在MySQL中设置自动递增属性。
Vishrant

Answers:


113

有时,即使执行,对模型或ORM所做的更改也可能无法准确反映在数据库上SchemaUpdate

如果错误实际上似乎缺乏明智的解释,请尝试重新创建数据库(或至少创建一个新数据库)并使用进行扩展SchemaExport


13
在许多情况下,只要将Hibernate设置为自动创建/管理数据库架构,就可以通过删除一个或多个有问题的表来解决此问题。要从托管模式中删除表,SET foreign_key_checks = 0;是您的朋友。只要确定SET foreign_key_checks = 1;完成即可。
aroth 2012年

我遇到了同样的问题并尝试使用您的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属性中使用update。进行更改并将其更新为Create,以便它可以创建表。

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

它为我工作。


1
对我来说有用。休眠+德比DB @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; 并与值createhbm2ddl.auto我的数据库架构应用更改属性。非常感谢....
Adam M. Gamboa G.

12

看一下GeneratedValue的策略。它通常看起来像:

@GeneratedValue(strategy=GenerationType.IDENTITY)

只是建议这个,尝试使用它代替.AUTO。
James McMahon

我明天必须检查一下,但是我几乎可以确定它不会解决。我看到很多使用GenerationType.AUTO的ID密钥。无论如何,我将确保明天进行测试。
2009年

确认-于事无补
安德烈Chalella

6

手动从数据库中删除表,然后重新运行该应用程序对我来说很有效。在我的情况下,我猜表创建不正确(有约束)。


很好的解决方案。没那么想。谢谢
梅尔'18

当我们对ID列或生成类型进行任何更改时,都应执行此操作
Jadda

5

我有这个问题。我的错误是我将可插入和可更新的文件设置为false,并试图在请求中设置该字段。在数据库中,此字段设置为NON NULL。

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

后来我将其更改为-insertable = true,可更新= true

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

后来效果很好。


默认情况下,可更新为true
Janac Meena

4

由于出现错误信息,我来到这里是因为我有两个同名表。


同样的事情发生在我身上:MySQL工作台只显示了一个“用户”表,但是,在我删除了数据库中的所有表之后,它突然显示了另一个“用户”表,该表以前是不可见的……
SND

3

另一个建议是检查是否对自动生成的字段使用了有效的类型。请记住,它不适用于String,但适用于Long:

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

@Constraints.Required
public String contents;

上面的语法适用于使用Hibernate作为JPA 2.0提供程序在MySQL中生成表。


将String更改为Long可以为我解决此问题。谢谢
jlars62

3

我有同样的问题。我找到了使用外键注释的Hibernate一对一映射示例教程,并按如下步骤进行操作:

使用此脚本创建数据库表:

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映射中添加了非null约束。有效

<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

请检查特定表中列ID的默认值是否为默认值。


0

我有同样的问题。我当时使用的是联接表,而我所拥有的全部都是一个行ID字段和两个外键。我不知道确切的原因,但我做了以下工作

  1. 将MySQL升级到社区5.5.13
  2. 重命名类和表
  3. 确保我有哈希码和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

如果数据库表具有未删除的旧列,则会引发相同的异常。

例如: attribute_id NOT NULL BIGINT(20),attributeId NOT NULL BIGINT(20),

在删除未使用的属性(在我的情况下为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

那这个呢:

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

希望对您有帮助。


0

尝试将Long对象类型更改为long基本类型(如果可以使用基本类型)。

我遇到了同样的问题,改变类型帮助了我。


0

我遇到了这个问题,因为我错误地将@Transient注解放在了该特定属性之上。就我而言,此错误是有道理的。


0

“字段'id'没有默认值”,因为您未GenerationType.IDENTITYGeneratedValue注释中声明。

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

0

此问题是因为有时您需要再次更新/创建数据库,或者有时如果您已在db表中添加了该字段,但没有添加实体类,则它无法插入任何null值或零,因此出现此错误。因此,请同时检查side.Db和Entity类。


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

当Model字段与db中的正确表字段不匹配时,我在GCP cloud sql中遇到了此类错误。示例:当在模型字段fieldName
中时,db中的表应具有字段field_name Fixing table字段名称对我有所帮助。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.