Jak dodać adnotacje do pola automatycznego zwiększania MYSQL z adnotacjami JPA

106

Prosto do rzeczy, problemem jest zapisanie operatora obiektu do bazy danych MySQL. Przed zapisaniem próbuję wybrać z tej tabeli i działa, więc jest połączenie z db.

Oto mój obiekt Operator:

@Entity
public class Operator{

   @Id
   @GeneratedValue
   private Long id;

   private String username;

   private String password;


   private Integer active;

   //Getters and setters...
}

Aby zapisać używam JPA EntityManagerjest persistmetoda.

Oto dziennik:

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

Z mojego punktu widzenia problemem jest konfiguracja z automatyczną inkrementacją, ale nie wiem gdzie.

Wypróbowałem kilka sztuczek, które tutaj widziałem: Hibernacja nie respektuje pola klucza podstawowego MySQL auto_increment Ale nic z tego nie działało

Jeśli będą potrzebne inne pliki konfiguracyjne, dostarczę je.

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`)
)
trywialnie
źródło
Jakiej wersji Hibernate używasz?
Steven Benitez

Odpowiedzi:

150

Aby użyć AUTO_INCREMENTkolumny MySQL , powinieneś użyć IDENTITYstrategii:

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

Co otrzymujesz korzystając AUTOz MySQL:

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

Co w rzeczywistości jest równoważne

@Id @GeneratedValue
private Long id;

Innymi słowy, twoje mapowanie powinno działać. Ale Hibernate powinien pomijać idkolumnę w instrukcji wstawiania SQL, a tak nie jest. Gdzieś musi być jakieś niedopasowanie.

Czy określiłeś dialekt MySQL w konfiguracji Hibernacji (prawdopodobnie MySQL5InnoDBDialectlub w MySQL5Dialectzależności od używanego silnika)?

Kto stworzył stół? Czy możesz pokazać odpowiedni DDL?

Kontynuacja: nie mogę odtworzyć twojego problemu. Korzystając z kodu twojej encji i twojego DDL, Hibernate generuje następujący (oczekiwany) SQL z MySQL:

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

Zauważ, że idzgodnie z oczekiwaniami w powyższej instrukcji brakuje kolumny.

Podsumowując, twój kod, definicja tabeli i dialekt są poprawne i spójne, powinno działać. Jeśli tak nie jest, być może coś nie jest zsynchronizowane (wykonaj czystą kompilację, dwukrotnie sprawdź katalog kompilacji itp.) Lub coś innego jest po prostu nie tak (sprawdź dzienniki pod kątem podejrzanych treści).

Jeśli chodzi o dialekt, jedyną różnicą między MySQL5Dialectlub MySQL5InnoDBDialectjest to, że później dodaje ENGINE=InnoDBdo obiektów tabeli podczas generowania DDL. Użycie jednego lub drugiego nie zmienia wygenerowanego kodu SQL.

Pascal Thivent
źródło
Pascal, masz rację, ale coś w moich plikach konfiguracyjnych jest po prostu nie tak. Może jakieś inne sugestie, teraz, gdy umieściłem nowe informacje i pliki konfiguracyjne?
trywialnie
9
@Pascal - Odkryłem, że potrzebuję @GeneratedValue (strategy = GenerationType.IDENTITY), aby AUTO_INCREMENT działało poprawnie podczas korzystania z JPA 2 / Hibernate 4.0.0.CR2 / JBoss AS 7. bit.ly/tdNyOJ
Joshua Davis
4
Zauważ, że dotyczy to MySQL . Z PostgreSQL nie dostajesz, @GeneratedValue(strategy=GenerationType.IDENTITY)kiedy piszesz @GeneratedValue(strategy=GenerationType.AUTO)i @GeneratedValue. Dlatego bądź ostrożny i staraj się być rozwlekły.
sajjadG
uwaga: w nowszych wersjach Hibernate i / lub MySQL / MariaDB GenerationType.AUTO będzie domyślnie używać GenerationType.TABLE. Co podczas aktualizacji może prowadzić do nieprzyjemnych problemów z niezsynchronizowanymi sekwencjami.
jwenting
nie zapomnij o odtworzeniu tabeli: spring.jpa.hibernate.ddl-auto = create. Z aktualizacją to nie zadziała
Glasnhost
38

Używając MySQL, działało tylko to podejście:

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

Pozostałe 2 podejścia podane przez Pascala w jego odpowiedzi nie działały w moim przypadku.

Jelle
źródło
Tak, opisałem to w moim pytaniu / odpowiedzi. stackoverflow.com/questions/39675714/…
Yan Khonski
Dzięki, to działa dla mnie, używam JPAz spring-boot i MySQL.
Osama Al-Banna
12

Dla każdego, kto to czyta i używa EclipseLink dla JPA 2.0, oto dwie adnotacje, których musiałem użyć, aby JPA utrwalił dane, gdzie „MySequenceGenerator” to dowolna nazwa, jaką chcesz nadać generatorowi, „myschema” to nazwa schemat w bazie danych, który zawiera obiekt sekwencji, a „mysequence” to nazwa obiektu sekwencji w bazie danych.

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

W przypadku użytkowników korzystających z EclipseLink (i prawdopodobnie innych dostawców JPA) KRYTYCZNYM jest ustawienie atrybutuocationSize na wartość INCREMENT zdefiniowaną dla sekwencji w bazie danych. Jeśli tego nie zrobisz, dostaniesz ogólny błąd trwałości i stracisz dużo czasu, próbując go wyśledzić, tak jak ja. Oto strona referencyjna, która pomogła mi pokonać to wyzwanie:

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

Aby nadać kontekst, oto czego używamy:

Java 7 Glassfish 3.1 PostgreSQL 9.1 PrimeFaces 3.2 / JSF 2.1

Ponadto, ze względu na lenistwo, zbudowałem to w Netbeans z kreatorami do generowania jednostek z DB, kontrolerów z jednostek i JSF z jednostek, a kreatorzy (oczywiście) nie wiedzą, jak radzić sobie z kolumnami identyfikatorów opartych na sekwencjach, więc będziesz musiał ręcznie dodać te adnotacje.

Max Awesome
źródło
6

Upewnij się, że typ danych id to Long zamiast String, jeśli to będzie ciąg, to adnotacja @GeneratedValue nie będzie działać, a generowanie sql dla

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

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

to musi być

create table VMS_AUDIT_RECORDS (id **bigint** not null auto_increment primary key (id))
ABHAY JOHRI
źródło
6

Jeśli używasz MySQL z Hibernate v3, możesz go używać, GenerationType.AUTOponieważ wewnętrznie będzie używał GenerationType.IDENTITY, co jest najbardziej optymalne dla MySQL.

Jednak w Hibernate v5 to się zmieniło. GenerationType.AUTOużyje, GenerationType.TABLEco generuje za dużo zapytań do wstawienia.

Możesz tego uniknąć, używając GenerationType.IDENTITY(jeśli MySQL jest jedyną bazą danych, której używasz) lub z tymi notacjami (jeśli masz wiele baz danych):

@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@GenericGenerator(name = "native", strategy = "native")
dmarquina
źródło
tak, trudna przyczyna niektórych paskudnych błędów regresji podczas aktualizacji aplikacji Spring, która pod maską również aktualizuje Hibernację.
jwenting
1

Próbowałem wszystkiego, ale nadal nie byłem w stanie tego zrobić, używam mysql, jpa z hibernacją, rozwiązałem swój problem, przypisując wartość id 0 w konstruktorze Poniżej znajduje się mój kod deklaracji identyfikatora

@Id
@Column(name="id",updatable=false,nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
M. Waseem Ullah Khan
źródło
1

Ponieważ podczas tworzenia bazy danych zdefiniowałeś identyfikator w typie int, musisz użyć tego samego typu danych również w klasie modelu. A ponieważ zdefiniowałeś identyfikator do automatycznego zwiększania w bazie danych, musisz wspomnieć o tym w klasie modelu, przekazując wartość „GenerationType.AUTO” do atrybutu „strategy” w adnotacji @GeneratedValue. Następnie kod wygląda jak poniżej.

@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
źródło
1

tak samo jak odpowiedział Pascal, tylko jeśli z jakiegoś powodu potrzebujesz użyć .AUTO, wystarczy dodać właściwości aplikacji:

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto = update
Jorge
źródło