Hibernate: “campo 'id' não tem um valor padrão”
-
03-07-2019 - |
Pergunta
Eu estou enfrentando o que eu acho que é um problema simples com Hibernate, mas não pode resolvê-lo (fóruns Hibernate sendo inacessível certamente não ajuda).
Eu tenho uma classe simples que eu 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 persistente é a seguinte:
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 de funcionamento real é simplesmente:
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();
}
Eu tentei algumas "estratégias" dentro da anotação GeneratedValue
mas ele simplesmente não parece trabalho. Inicializar id
também não ajuda! (Por exemplo Long id = 20L
).
Alguém poderia lançar alguma luz?
EDIT 2: confirmada: mexer with@GeneratedValue(strategy = GenerationType.XXX)
não resolvê-lo
RESOLVIDO: recriar o banco de dados resolveu o problema
Solução
Às vezes as alterações feitas ao modelo ou ao ORM podem não refletir com precisão no banco de dados, mesmo depois de uma execução de SchemaUpdate
.
Se o erro realmente parece que falta uma explicação sensata, tente recriar o banco de dados (ou pelo menos criar uma nova) e andaimes com SchemaExport
.
Outras dicas
Se você quiser que o MySQL automaticamente produzir chaves primárias, em seguida, você tem que dizer isso ao criar a tabela. Você não tem que fazer isso em Oracle.
na chave primária você tem que 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;
}
}
você deve estar usando atualização em sua propriedade hbm2ddl. fazer as mudanças e atualizar-lo para criar de modo que possa criar a tabela.
<property name="hbm2ddl.auto">create</property>
Ela trabalhou para mim.
Dê uma olhada na estratégia da GeneratedValue
. Ele normalmente é algo como:
@GeneratedValue(strategy=GenerationType.IDENTITY)
Outra sugestão é verificar se você usar um tipo válido para o campo gerado automaticamente. Lembre-se que ele 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 funcionou para gerar tabelas no MySQL usando Hibernate como provedor JPA 2.0.
Eu tive o mesmo problema. Achei o tutorial Hibernate One-To-One Exemplo Mapping usando a chave Foreign Anotação e seguiu passo a passo como abaixo:
Crie a 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á 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
Eu vim aqui por causa da mensagem de erro, Acontece que eu tinha duas tabelas com o mesmo nome.
Basta adicionar não-nula restrição
Eu tive o mesmo problema. Acabei de adicionar restrição de não nulo 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>
Deixar cair a tabela do banco de dados manualmente e, em seguida, re-executar o aplicativo funcionou para mim. No meu caso a tabela não foi criado corretamente (com restrições), eu acho.
Eu tive esse problema. Meu erro foi que eu tinha definido os fileds inserível e atualizáveis ??como falso e estava tentando definir o campo no pedido. Este campo é definido como não 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 - inserível = true, atualizável = true
@ManyToOne
@JoinColumn(name="roles_id", referencedColumnName = "id", insertable = true, updatable = true, nullable=false)
@JsonBackReference
//@JsonIgnore
private Role role;
Ele funcionou perfeitamente depois.
Por favor, verifique se o valor padrão para o ID de coluna em particular table.if não fazê-lo como padrão
Eu tive o mesmo problema. Eu estava usando uma tabela associativa e tudo que eu tive com um campo de linha id e duas chaves estrangeiras. Eu não sei exatamente o causou, mas eu fiz o seguinte
- MySQL atualizado para comunidade 5.5.13
- Mudar o nome da classe e tabela
-
Certifique-se de que eu tinha hashcode e iguala métodos
@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;
A mesma exceção foi lançada se uma tabela DB tinha uma coluna unremoved de idade.
Por exemplo:
attribute_id NOT NULL BIGINT(20),
e attributeId NOT NULL BIGINT(20),
Depois de remover o atributo não é usado, no meu caso, contractId , o problema foi resolvido.
Isto aconteceu-me com uma relação @ManyToMany
. Eu tinha anotado um dos campos no relacionamento com @JoinTable
, eu removi que e usado o atributo mappedBy
em @ManyToMany vez.
Além do que foi mencionado acima, não se esqueça ao criar a tabela sql para fazer o AUTO INCREMENT 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
);
Eu tentei o código e no meu caso o código abaixo resolver a questão. Eu não tinha resolvido o esquema corretamente
@Entity
@Table(name="table"
,catalog="databasename"
)
Por favor, tente adicionar ,catalog="databasename"
o mesmo que eu fiz.
,catalog="databasename"
No meu caso, Eu alterei que ofender tabelas e o campo "id" em questão eu fiz isso AUTO_INCREMENT, eu ainda preciso descobrir por que em tempo de implantação não foi tornando-se "AUTO_INCREMENT" para que eu tenho que fazer isso por mim!
O que sobre isso:
<set name="fieldName" cascade="all">
<key column="id" not-null="true" />
<one-to-many class="com.yourClass"/>
</set>
Espero que ajude você.
Talvez que é o problema com o esquema da tabela. remover a tabela e execute novamente o aplicativo.
Tente mudar tipo Long
objeto para long
tipo primitivo (se estiver usando primitivas é ok para você).
Eu tive o mesmo problema e alterar o tipo de me ajudou.
Eu tive este problema, por engano eu tinha colocado anotação @Transient
acima desse atributo particular. No meu caso esse erro faz sentido.
Adicionar um hashCode()
método para seu bean de entidade de classe e tentar novamente