Je fais face à ce que je pense est un problème simple avec Hibernate, mais je ne peux pas le résoudre (les forums de Hibernate étant inaccessibles, cela n’aide en rien).
J'ai un cours simple, je voudrais persister, mais continue à obtenir:
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 ]
Le code pertinent pour la classe persistante est:
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;
}
}
Et le code courant est tout simplement:
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();
}
J'ai essayé quelques "stratégies" dans l'annotation GeneratedValue
mais cela ne semble tout simplement pas fonctionner. Initialiser id
n'aide pas non plus! (par exemple Long id = 20L
).
Quelqu'un pourrait-il nous éclairer?
EDIT 2: confirmé: déconner avec @GeneratedValue(strategy = GenerationType.XXX)
ne le résout pas
RESOLU: recréer la base de données a résolu le problème
Parfois, les modifications apportées au modèle ou à l'ORM peuvent ne pas refléter correctement la base de données, même après l'exécution de SchemaUpdate
.
Si l'erreur semble manquer d'une explication sensée, essayez de recréer la base de données (ou du moins d'en créer une nouvelle) et de l'échafauder avec SchemaExport
.
Si vous voulez que MySQL produise automatiquement des clés primaires, vous devez le dire lors de la création de la table. Vous n'êtes pas obligé de faire cela dans Oracle.
Sur la clé primaire, vous devez inclure AUTO_INCREMENT
. Voir l'exemple ci-dessous.
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;
Voici l'entité
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;
}
}
Jetez un coup d'œil à la stratégie de GeneratedValue
. Cela ressemble généralement à quelque chose comme:
@GeneratedValue(strategy=GenerationType.IDENTITY)
vous devez utiliser update dans votre propriété hbm2ddl. apportez les modifications et mettez-le à jour en créant afin qu'il puisse créer la table.
<property name="hbm2ddl.auto">create</property>
Cela a fonctionné pour moi.
Une autre suggestion consiste à vérifier que vous utilisez un type valide pour le champ généré automatiquement. Rappelez-vous que cela ne fonctionne pas avec String, mais avec Long:
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Long id;
@Constraints.Required
public String contents;
La syntaxe ci-dessus a fonctionné pour générer des tables dans MySQL en utilisant Hibernate en tant que fournisseur JPA 2.0.
J'ai eu le même problème. J'ai trouvé le tutoriel Exemple de mappage one-to-one Hibernate avec une annotation de clé étrangère et l'ai suivi étape par étape, comme ci-dessous:
Créer une table de base de données avec ce 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)
);
Voici les entités avec les tables ci-dessus
@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;
}
Le problème était résolu.
Remarque: la clé primaire doit être définie sur AUTO_INCREMENT.
Il suffit d'ajouter une contrainte non nulle
J'ai eu le même problème. Je viens d'ajouter une contrainte non nulle dans le mappage xml. Ça a marché
<set name="phone" cascade="all" lazy="false" >
<key column="id" not-null="true" />
<one-to-many class="com.practice.phone"/>
</set>
La suppression manuelle de la table de la base de données, puis la réexécution de l'application ont fonctionné pour moi. Dans mon cas, la table n'a pas été créée correctement (avec des contraintes), je suppose.
Je suis venu ici à cause du message d'erreur. Il s'avère que j'avais deux tables du même nom.
J'ai eu ce problème. Mon erreur était que j'avais défini les champs insérables et pouvant être mis à jour comme faux et que j'essayais de définir le champ dans la demande. Ce champ est défini sur NON NULL dans la base de données.
@ManyToOne
@JoinColumn(name="roles_id", referencedColumnName = "id", insertable = false, updatable = false, nullable=false)
@JsonBackReference
private Role role;
Plus tard je l'ai changé en - insertable = true, updatable = true
@ManyToOne
@JoinColumn(name="roles_id", referencedColumnName = "id", insertable = true, updatable = true, nullable=false)
@JsonBackReference
//@JsonIgnore
private Role role;
Cela a parfaitement fonctionné plus tard.
En plus de ce qui est mentionné ci-dessus, n'oubliez pas lors de la création de la table SQL pour créer le AUTO INCREMENT comme dans cet exemple
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
);
J'ai essayé le code et dans mon cas, le code ci-dessous résout le problème. Je n'avais pas réglé le schéma correctement
@Entity
@Table(name="table"
,catalog="databasename"
)
S'il vous plaît essayez d'ajouter ,catalog="databasename"
le même que j'ai fait.
,catalog="databasename"
Veuillez vérifier si la valeur par défaut de l'id de colonne dans la table en particulier ne l'est pas par défaut.
"Le champ 'id' n'a pas de valeur par défaut" car vous n'avez pas déclaré GenerationType.IDENTITY
dans GeneratedValue
Annotation.
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
Et ça:
<set name="fieldName" cascade="all">
<key column="id" not-null="true" />
<one-to-many class="com.yourClass"/>
</set>
J'espère que ça t'aide.
Peut-être que c'est le problème avec le schéma de table. laisse tomber la table et relancez l'application.
J'ai eu ce problème, par erreur j'ai placé l'annotation @Transient
au-dessus de cet attribut particulier. Dans mon cas, cette erreur a du sens.
J'ai eu le même problème. J'utilisais une table de jointure et tout ce que j'avais avec un champ ID de ligne et deux clés étrangères. Je ne connais pas la cause exacte mais j’ai fait ce qui suit
Assurez-vous que j'ai eu le hashcode et les méthodes équivalentes
@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;
Essayez de changer le type d'objet Long
en long
type primitif (si utiliser des primitives vous convient).
J'ai eu le même problème et changer de type m'a aidé.
Dans mon cas, J'ai modifié les tables incriminées et le champ "id" en question, je l'ai fait AUTO_INCREMENT, je dois encore comprendre pourquoi, au moment du déploiement, il ne le faisait pas "AUTO_INCREMENT", de sorte que je devais le faire. par moi-même!
La même exception a été levée si une table de base de données contenait une ancienne colonne non supprimée.
Par exemple: attribute_id NOT NULL BIGINT(20),
et attributeId NOT NULL BIGINT(20),
Après avoir supprimé l'attribut non utilisé, dans mon cas, contractId , le problème a été résolu.
Cela m'est arrivé avec une relation @ManyToMany
. J'avais annoté l'un des champs dans la relation avec @JoinTable
, je l'ai supprimé et utilisé l'attribut mappedBy
sur @ManyToMany à la place.