Annotieren des MYSQL-Autoincrement-Felds mit JPA-Annotationen

105

Das Problem besteht darin, den Objektoperator in MySQL DB zu speichern. Vor dem Speichern versuche ich, aus dieser Tabelle auszuwählen, und es funktioniert, ebenso wie die Verbindung zu db.

Hier ist mein Operator-Objekt:

@Entity
public class Operator{

   @Id
   @GeneratedValue
   private Long id;

   private String username;

   private String password;


   private Integer active;

   //Getters and setters...
}

So speichern ich PPV EntityManager‚s - persistMethode.

Hier ist ein Protokoll:

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

So wie ich es sehe, ist das Problem die Konfiguration mit automatischer Inkrementierung, aber ich kann nicht herausfinden, wo.

Ich habe einige Tricks ausprobiert, die ich hier gesehen habe: Ruhezustand ohne Berücksichtigung des MySQL-Primärschlüsselfelds auto_increment Aber nichts davon hat funktioniert

Wenn andere Konfigurationsdateien benötigt werden, werde ich diese bereitstellen.

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`)
)
trivunm
quelle
Welche Version von Hibernate verwenden Sie?
Steven Benitez

Antworten:

150

Um eine MySQL- AUTO_INCREMENTSpalte zu verwenden, müssen Sie eine IDENTITYStrategie verwenden:

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

Welches ist, was Sie erhalten würden, wenn Sie AUTOmit MySQL verwenden:

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

Welches ist eigentlich gleichbedeutend mit

@Id @GeneratedValue
private Long id;

Mit anderen Worten, Ihr Mapping sollte funktionieren. Im Ruhezustand sollte die idSpalte in der SQL-Anweisung insert jedoch weggelassen werden. Irgendwo muss es eine Art Missverhältnis geben.

Haben Sie in Ihrer Hibernate-Konfiguration einen MySQL-Dialekt angegeben (wahrscheinlich MySQL5InnoDBDialectoder MySQL5Dialectabhängig von der verwendeten Engine)?

Wer hat die Tabelle erstellt? Können Sie die entsprechende DDL anzeigen?

Follow-up: Ich kann Ihr Problem nicht reproduzieren. Mit dem Code Ihrer Entität und Ihrer DDL generiert Hibernate mit MySQL das folgende (erwartete) SQL:

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

Beachten Sie, dass die idSpalte in der obigen Anweisung erwartungsgemäß fehlt.

Zusammenfassend lässt sich sagen, dass Ihr Code, die Tabellendefinition und der Dialekt korrekt und kohärent sind. Es sollte funktionieren. Wenn dies nicht der Fall ist, ist möglicherweise etwas nicht synchron (führen Sie einen sauberen Build durch, überprüfen Sie das Build-Verzeichnis noch einmal usw.) oder etwas anderes stimmt einfach nicht (überprüfen Sie die Protokolle auf verdächtige Daten).

In Bezug auf den Dialekt besteht der einzige Unterschied zwischen MySQL5Dialectoder MySQL5InnoDBDialectdarin, dass der letztere ENGINE=InnoDBbeim Generieren der DDL zu den Tabellenobjekten hinzugefügt wird. Die Verwendung des einen oder anderen ändert nichts an der generierten SQL.

Pascal Thivent
quelle
Pascal, da hast du recht, aber etwas in meinen Konfigurationsdateien stimmt einfach nicht. Irgendwelche anderen Vorschläge vielleicht, nachdem ich neue Informationen und Konfigurationsdateien abgelegt habe?
trivunm
9
@Pascal - Ich habe festgestellt, dass ich @GeneratedValue (Strategie = GenerationType.IDENTITY) benötige, damit AUTO_INCREMENT bei Verwendung von JPA 2 / Hibernate 4.0.0.CR2 / JBoss AS 7 ordnungsgemäß funktioniert. Bit.ly/tdNyOJ
Joshua Davis
4
Beachten Sie, dass dies für MySQL gilt . Mit PostgreSQL bekommen Sie nicht, @GeneratedValue(strategy=GenerationType.IDENTITY)wenn Sie schreiben @GeneratedValue(strategy=GenerationType.AUTO)und @GeneratedValue. Sei also vorsichtig und versuche wortreich zu sein.
SajjadG
Hinweis: Bei neueren Versionen von Hibernate und / oder MySQL / MariaDB generiert GenerationType.AUTO standardmäßig GenerationType.TABLE. Was beim Upgrade zu unangenehmen Problemen mit nicht synchronisierten Sequenzen führen kann.
Jwenting
Vergessen Sie nicht, die Tabelle neu zu erstellen: spring.jpa.hibernate.ddl-auto = create. Mit Update wird es nicht funktionieren
Glasnhost
38

Mit MySQL funktionierte nur dieser Ansatz für mich:

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

Die anderen beiden Ansätze, die Pascal in seiner Antwort angegeben hat, haben bei mir nicht funktioniert.

Jelle
quelle
Ja, ich habe dies in meiner Frage / Antwort berücksichtigt. stackoverflow.com/questions/39675714/…
Yan Khonski
Danke, es funktioniert für mich, ich benutze JPAmit spring-boot und MySQL.
Osama Al-Banna
12

Für alle, die dies lesen und EclipseLink für JPA 2.0 verwenden, sind hier die beiden Anmerkungen, die ich verwenden musste, damit JPA Daten beibehält. Dabei ist "MySequenceGenerator" der Name, den Sie dem Generator geben möchten. "Myschema" ist der Name des Schema in Ihrer Datenbank, das das Sequenzobjekt enthält, und "mysequence" ist der Name des Sequenzobjekts in der Datenbank.

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

Für Benutzer von EclipseLink (und möglicherweise anderer JPA-Anbieter) ist es KRITISCH, dass Sie das Attribut assignSize so einstellen, dass es mit dem für Ihre Sequenz in der Datenbank definierten INCREMENT-Wert übereinstimmt. Wenn Sie dies nicht tun, erhalten Sie einen generischen Persistenzfehler und verschwenden viel Zeit damit, ihn aufzuspüren, wie ich es getan habe. Hier ist die Referenzseite, die mir geholfen hat, diese Herausforderung zu meistern:

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

Um den Kontext zu verdeutlichen, verwenden wir Folgendes:

Java 7 Glassfish 3.1 PostgreSQL 9.1 PrimeFaces 3.2 / JSF 2.1

Aus Gründen der Faulheit habe ich dies in Netbeans mit den Assistenten zum Generieren von Entitäten aus DB, Controllern aus Entitäten und JSF aus Entitäten erstellt, und die Assistenten wissen (offensichtlich) nicht, wie sie mit sequenzbasierten ID-Spalten umgehen sollen Sie müssen diese Anmerkungen manuell hinzufügen.

Max Super
quelle
6

Wenn Sie MySQL mit Hibernate v3 verwenden, ist es in Ordnung, es zu verwenden, GenerationType.AUTOda es intern verwendet wird GenerationType.IDENTITY, was für MySQL am optimalsten ist.

In Hibernate v5 hat sich dies jedoch geändert. GenerationType.AUTOwird verwendet, GenerationType.TABLEwas zu viele Abfragen für das Einfügen generiert.

Sie können dies vermeiden, GenerationType.IDENTITYwenn Sie (wenn MySQL die einzige Datenbank ist, die Sie verwenden) oder mit diesen Notationen (wenn Sie mehrere Datenbanken haben):

@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@GenericGenerator(name = "native", strategy = "native")
Dmarquina
quelle
Ja, eine knifflige Ursache für einige böse Regressionsfehler beim Upgrade Ihrer Spring-Anwendung, die unter der Haube auch den Ruhezustand aktualisiert.
Jwenting
5

Stellen Sie sicher, dass der ID-Datentyp Long anstelle von String ist. Wenn dies ein String ist, funktioniert die Annotation @GeneratedValue nicht und die SQL-Generierung für

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

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

das muss sein

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

Ich habe alles versucht, aber ich konnte das immer noch nicht. Ich verwende MySQL, JPA mit Ruhezustand. Ich habe mein Problem behoben, indem ich im Konstruktor den Wert ID 0 zugewiesen habe. Nachfolgend ist mein ID-Deklarationscode aufgeführt

@Id
@Column(name="id",updatable=false,nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
M. Waseem Ullah Khan
quelle
1

Da Sie bei der Datenbankerstellung die ID im Typ int definiert haben, müssen Sie denselben Datentyp auch in der Modellklasse verwenden. Und da Sie die ID für das automatische Inkrementieren in der Datenbank definiert haben, müssen Sie sie in der Modellklasse erwähnen, indem Sie den Wert 'GenerationType.AUTO' an das Attribut 'Strategie' in der Annotation @GeneratedValue übergeben. Dann wird der Code wie folgt.

@Entity
public class Operator{

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

  private String username;

  private String password;

  private Integer active;

  //Getters and setters...
}
Anjali Pavithra
quelle
1

Wie Pascal geantwortet, müssen Sie nur, wenn Sie aus irgendeinem Grund .AUTO verwenden müssen, nur Ihre Anwendungseigenschaften hinzufügen:

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto = update
Jorge
quelle
0

Können Sie überprüfen, ob Sie eine Verbindung zur richtigen Datenbank hergestellt haben? Als ich vor dem gleichen Problem stand, stellte ich schließlich fest, dass ich mich mit einer anderen Datenbank verbunden hatte.

Identität unterstützt Identitätsspalten in DB2, MySQL, MS SQL Server, Sybase und HypersonicSQL. Der zurückgegebene Bezeichner ist vom Typ long, short oder int.

Weitere Informationen: http://docs.jboss.org/hibernate/orm/3.5/reference/en/html/mapping.html#mapping-declaration-id

Mohan Reddy
quelle