Cara membuat anotasi bidang autoincrement MYSQL dengan anotasi JPA

106

Langsung ke intinya, masalahnya adalah menyimpan Operator objek ke MySQL DB. Sebelum menyimpan, saya mencoba untuk memilih dari tabel ini dan berhasil, begitu juga koneksi ke db.

Ini adalah objek Operator saya:

@Entity
public class Operator{

   @Id
   @GeneratedValue
   private Long id;

   private String username;

   private String password;


   private Integer active;

   //Getters and setters...
}

Untuk menyimpan Saya menggunakan JPA EntityManager'spersist metode.

Berikut beberapa log:

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

Menurut saya, masalahnya adalah konfigurasi dengan penambahan otomatis tetapi saya tidak tahu di mana.

Mencoba beberapa trik yang pernah saya lihat di sini: Hibernate tidak menghormati bidang kunci utama auto_increment MySQL Tapi tidak ada yang berhasil

Jika ada file konfigurasi lain yang diperlukan, saya akan menyediakannya.

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
sumber
Versi Hibernate apa yang Anda gunakan?
Steven Benitez

Jawaban:

150

Untuk menggunakan AUTO_INCREMENTkolom MySQL , Anda harus menggunakan IDENTITYstrategi:

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

Yang akan Anda dapatkan saat menggunakan AUTOMySQL:

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

Yang sebenarnya setara dengan

@Id @GeneratedValue
private Long id;

Dengan kata lain, pemetaan Anda harus berfungsi. Tapi Hibernate harus menghilangkanid kolom dalam pernyataan insert SQL, dan sebenarnya tidak. Pasti ada semacam ketidakcocokan di suatu tempat.

Apakah Anda menentukan dialek MySQL dalam konfigurasi Hibernate Anda (mungkin MySQL5InnoDBDialectatauMySQL5Dialect tergantung pada mesin yang Anda gunakan)?

Juga, siapa yang membuat tabel tersebut? Bisakah Anda menunjukkan DDL yang sesuai?

Tindak lanjut: Saya tidak dapat mereproduksi masalah Anda. Menggunakan kode entitas Anda dan DDL Anda , Hibernate menghasilkan SQL (diharapkan) berikut dengan MySQL:

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

Perhatikan bahwa file id kolom tidak ada dari pernyataan di atas, seperti yang diharapkan.

Singkatnya, kode Anda, definisi tabel, dan dialeknya benar dan koheren, seharusnya berfungsi. Jika tidak untuk Anda, mungkin ada sesuatu yang tidak sinkron (lakukan build bersih, periksa ulang direktori build, dll) atau ada hal lain yang salah (periksa log untuk melihat apakah ada yang mencurigakan).

Mengenai dialek, satu - satunya perbedaan antara MySQL5Dialectatau MySQL5InnoDBDialectadalah bahwa nanti menambahkan ENGINE=InnoDBobjek tabel saat membuat DDL. Menggunakan satu atau lainnya tidak mengubah SQL yang dihasilkan.

Pascal Thivent
sumber
Pascal, Anda benar tentang itu tetapi ada sesuatu di file konfigurasi saya yang tidak benar. Saran lain mungkin, sekarang saya telah meletakkan informasi baru dan file konfigurasi?
trivunm
9
@Pascal - Saya telah menemukan bahwa saya membutuhkan @GeneratedValue (strategy = GenerationType.IDENTITY) agar AUTO_INCREMENT berfungsi dengan baik saat menggunakan JPA 2 / Hibernate 4.0.0.CR2 / JBoss AS 7. bit.ly/tdNyOJ
Joshua Davis
4
Perhatikan bahwa itu benar untuk MySQL . Dengan PostgreSQL Anda tidak mendapatkan @GeneratedValue(strategy=GenerationType.IDENTITY)saat Anda menulis @GeneratedValue(strategy=GenerationType.AUTO)dan @GeneratedValue. Jadi berhati-hatilah dan cobalah untuk bertele-tele.
sajjadG
catatan: dengan versi Hibernate dan / atau MySQL / MariaDB GenerationType yang lebih baru. AUTO akan default ke GenerationType.TABLE. Yang ketika meningkatkan dapat menyebabkan masalah buruk dengan urutan yang tidak sinkron.
jwenting
jangan lupa untuk membuat ulang tabel: spring.jpa.hibernate.ddl-auto = create. Dengan pembaruan itu tidak akan berfungsi
Glasnhost
38

Menggunakan MySQL, hanya pendekatan ini yang berhasil untuk saya:

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

2 pendekatan lainnya yang dinyatakan oleh Pascal dalam jawabannya tidak berhasil untuk saya.

Jelle
sumber
Ya, saya merujuk ini dalam pertanyaan / jawaban saya. stackoverflow.com/questions/39675714/…
Yan Khonski
Terima kasih, ini berhasil untuk saya, saya menggunakan JPAdengan spring-boot dan MySQL.
Osama Al-Banna
12

Bagi siapa pun yang membaca ini yang menggunakan EclipseLink untuk JPA 2.0, berikut adalah dua anotasi yang harus saya gunakan untuk membuat JPA menyimpan data, di mana "MySequenceGenerator" adalah nama apa pun yang ingin Anda berikan pada generator, "myschema" adalah nama dari skema di database Anda yang berisi objek sequence, dan "mysequence" adalah nama objek sequence di database.

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

Bagi mereka yang menggunakan EclipseLink (dan mungkin penyedia JPA lainnya), PENTING bahwa Anda menyetel atribut alokasiSize agar cocok dengan nilai INCREMENT yang ditentukan untuk urutan Anda dalam database. Jika tidak, Anda akan mengalami kegagalan ketekunan umum, dan membuang banyak waktu untuk mencoba melacaknya, seperti yang saya lakukan. Berikut halaman referensi yang membantu saya mengatasi tantangan ini:

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

Juga, untuk memberi konteks, inilah yang kami gunakan:

Java 7 Glassfish 3.1 PostgreSQL 9.1 PrimeFaces 3.2 / JSF 2.1

Juga, demi kemalasan, saya membangun ini di Netbeans dengan penyihir untuk menghasilkan Entitas dari DB, Pengendali dari Entitas, dan JSF dari Entitas, dan penyihir (jelas) tidak tahu bagaimana menangani kolom ID berbasis urutan, jadi Anda harus menambahkan anotasi ini secara manual.

Max Luar Biasa
sumber
6

Pastikan bahwa tipe data id adalah Long, bukan String, jika itu akan menjadi string maka anotasi @GeneratedValue tidak akan berfungsi dan sql menghasilkan

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

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

itu perlu

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

Jika Anda menggunakan Mysql dengan Hibernate v3 tidak masalah untuk digunakan GenerationType.AUTOkarena secara internal akan digunakan GenerationType.IDENTITY, yang paling optimal untuk MySQL.

Namun di Hibernate v5, Ini telah berubah. GenerationType.AUTOakan menggunakanGenerationType.TABLE yang menghasilkan banyak kueri untuk penyisipan.

Anda dapat menghindarinya dengan menggunakan GenerationType.IDENTITY(jika MySQL adalah satu-satunya database yang Anda gunakan) atau dengan notasi berikut (jika Anda memiliki beberapa database):

@GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
@GenericGenerator(name = "native", strategy = "native")
dmarquina.dll
sumber
ya, penyebab rumit untuk beberapa kesalahan regresi yang tidak menyenangkan saat mengupgrade aplikasi Spring Anda yang juga mengupgrade Hibernate.
jwenting
1

Saya mencoba segalanya, tetapi tetap tidak dapat melakukan itu, saya menggunakan mysql, jpa dengan hibernate, saya menyelesaikan masalah saya dengan menetapkan nilai id 0 di konstruktor Berikut ini adalah kode deklarasi id saya

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

Karena Anda telah menentukan id dalam tipe int pada pembuatan database, Anda juga harus menggunakan tipe data yang sama di kelas model. Dan karena Anda telah mendefinisikan id ke auto increment dalam database, Anda harus menyebutkannya di kelas model dengan meneruskan nilai 'GenerationType.AUTO' ke dalam atribut 'strategy' dalam anotasi @GeneratedValue. Kemudian kodenya menjadi seperti di bawah ini.

@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
sumber
1

sama dengan jawaban pascal, hanya jika Anda perlu menggunakan .AUTO karena alasan tertentu Anda hanya perlu menambahkan properti aplikasi Anda:

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