web-dev-qa-db-fra.com

Comment annoter un champ auto-incrémenté MYSQL avec des annotations JPA

Droit au but, le problème est la sauvegarde de l’objet Operator dans MySQL DB . Avant de sauvegarder, j’essaie de sélectionner dans cette table et cela fonctionne, la connexion à db aussi.

Voici mon objet opérateur:

@Entity
public class Operator{

   @Id
   @GeneratedValue
   private Long id;

   private String username;

   private String password;


   private Integer active;

   //Getters and setters...
}

Pour enregistrer, j'utilise la méthode JPA EntityManager’s s persist.

Voici un journal:

Hibernate: insert into Operator (active, password, username, id) values (?, ?, ?, ?)
com.mysql.jdbc.JDBC4PreparedStatement@15724a0: insert into Operator (active,password, username, id) values (0, 'pass', 'user', ** NOT SPECIFIED **)

Selon moi, le problème est la configuration avec incrémentation automatique, mais je ne peux pas savoir où.

J'ai essayé quelques astuces que j'ai vues ici: Hibernate ne respecte pas MySQL auto_increment le champ de clé primaire Mais rien de cela n'a fonctionné

Si d'autres fichiers de configuration sont nécessaires, je les fournirai.

DDL:

CREATE TABLE `operator` ( 
`id` INT(10) NOT NULL AUTO_INCREMENT,
`first_name` VARCHAR(40) NOT NULL,
`last_name` VARCHAR(40) NOT NULL,
`username` VARCHAR(50) NOT NULL,
`password` VARCHAR(50) NOT NULL,
`active` INT(1) NOT NULL,
PRIMARY KEY (`id`)
)
90
trivunm

Pour utiliser une colonne MySQL AUTO_INCREMENT, vous devez utiliser une stratégie IDENTITY:

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

Quel est ce que vous obtiendrez en utilisant AUTO avec MySQL:

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

Qui est équivalent à

@Id @GeneratedValue
private Long id;

En d'autres termes, votre cartographie devrait fonctionner. Mais Hibernate devrait omettre la colonne id dans l’instruction SQL Insert, ce qui n’est pas le cas. Il doit y avoir une sorte de discordance quelque part.

Avez-vous spécifié un dialecte MySQL dans votre configuration Hibernate (probablement MySQL5InnoDBDialect ou MySQL5Dialect en fonction du moteur utilisé)? 

Aussi, qui a créé la table? Pouvez-vous montrer le DDL correspondant?

Suivi: Je ne peux pas reproduire votre problème. En utilisant le code de votre entité et de votre DDL, Hibernate génère le code SQL (attendu) suivant avec MySQL:

insert 
into
    Operator
    (active, password, username) 
values
    (?, ?, ?)

Notez que la colonne id est absente de l'instruction ci-dessus, comme prévu. 

En résumé, votre code, la définition de la table et le dialecte sont corrects et cohérents, cela devrait fonctionner. Si ce n'est pas votre cas, il se peut que quelque chose ne soit pas synchronisé (effectuez une nouvelle construction, vérifiez le répertoire de construction, etc.) ou que quelque chose d'autre soit simplement erroné (vérifiez que les journaux ne contiennent rien de suspect).

En ce qui concerne le dialecte, la différence uniquement entre MySQL5Dialect et MySQL5InnoDBDialect est que ce dernier ajoute ENGINE=InnoDB aux objets de la table lors de la génération du DDL. L'utilisation de l'un ou de l'autre ne modifie pas le SQL généré.

121
Pascal Thivent

En utilisant MySQL, seule cette approche fonctionnait pour moi:

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

Les 2 autres approches indiquées par Pascal dans sa réponse ne fonctionnaient pas pour moi.

29
Jelle

Pour tous ceux qui lisent ceci et qui utilisent EclipseLink for JPA 2.0, voici les deux annotations que je devais utiliser pour que JPA conserve les données, où "MySequenceGenerator" est le nom que vous souhaitez donner au générateur, "myschema" est le nom du schéma dans votre base de données contenant l’objet de séquence et "mysequence" est le nom de l’objet de séquence dans la base de données.

@GeneratedValue(strategy= GenerationType.SEQUENCE, generator="MySequenceGenerator")
@SequenceGenerator(allocationSize=1, schema="myschema",  name="MySequenceGenerator", sequenceName = "mysequence")

Pour ceux qui utilisent EclipseLink (et éventuellement d'autres fournisseurs JPA), il est CRITIQUE de définir l'attribut allocationSize pour qu'il corresponde à la valeur INCREMENT définie pour votre séquence dans la base de données. Si vous ne le faites pas, vous obtiendrez un échec de persistance générique et vous perdrez beaucoup de temps à essayer de le localiser, comme je l'ai fait. Voici la page de référence qui m'a aidé à surmonter ce défi:

http://wiki.Eclipse.org/EclipseLink/Examples/JPA/PrimaryKey#Using_Sequence_Objects

Aussi, pour donner un contexte, voici ce que nous utilisons:

Java 7 Glassfish 3.1 PostgreSQL 9.1 PrimeFaces 3.2/JSF 2.1

De plus, par souci de paresse, j’ai construit cela dans Netbeans avec les assistants permettant de générer des entités à partir d’une base de données, des contrôleurs d’entités et un fichier JSF à partir d’entités. vous devrez ajouter manuellement ces annotations.

11
Max Awesome

Assurez-vous que le type de données id est Long au lieu de String, si sera une chaîne puis l'annotation @GeneratedValue ne fonctionnera pas et le sql générant pour

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

create table VMS_AUDIT_RECORDS (id **varchar(255)** not null auto_increment primary key (id))

cela doit être

create table VMS_AUDIT_RECORDS (id **bigint** not null auto_increment primary key (id))
3
ABHAY JOHRI

Si vous utilisez Mysql avec Hibernate v3, il est correct d'utiliser GenerationType.AUTO car en interne, il utilisera GenerationType.IDENTITY, qui est le plus optimal pour MySQL.

Cependant, dans Hibernate v5, cela a changé. GenerationType.AUTO utilisera GenerationType.TABLE qui génère beaucoup de requêtes pour l'insertion.

Vous pouvez éviter cela en utilisant GenerationType.IDENTITY (si MySQL est la seule base de données que vous utilisez) ou avec ces notations (si vous avez plusieurs bases de données):

@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@GenericGenerator(name = "native", strategy = "native")
1
dmarquina

Comme vous avez défini l'ID dans int type lors de la création de la base de données, vous devez également utiliser le même type de données dans la classe de modèle. Et comme vous avez défini l'ID à incrémenter automatiquement dans la base de données, vous devez le mentionner dans la classe de modèle en transmettant la valeur 'GenerationType.AUTO' à l'attribut 'stratégie' de l'annotation @GeneratedValue. Alors le code devient comme ci-dessous.

@Entity
public class Operator{

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

  private String username;

  private String password;

  private Integer active;

  //Getters and setters...
}
0
Anjali Pavithra

J'ai tout essayé, mais je ne pouvais toujours pas le faire, j'utilise mysql, jpa avec hibernate, j'ai résolu mon problème en attribuant la valeur id 0 au constructeur Voici le code de déclaration de mon identifiant

@Id
@Column(name="id",updatable=false,nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
0

pouvez-vous vérifier si vous êtes connecté à la bonne base de données? comme j'étais confronté au même problème, mais finalement j'ai trouvé que je me suis connecté à une base de données différente.

identity prend en charge les colonnes d'identité dans DB2, MySQL, MS SQL Server, Sybase et HypersonicSQL. L'identifiant renvoyé est de type long, short ou int.

Plus d'infos: http://docs.jboss.org/hibernate/orm/3.5/reference/en/html/mapping.html#mapping-declaration-id

0
Mohan Reddy