วิธีใส่คำอธิบายประกอบฟิลด์การเพิ่มอัตโนมัติ MYSQL ด้วยคำอธิบายประกอบ JPA


106

ตรงประเด็นปัญหาคือการบันทึก object Operator ลงใน MySQL DB ก่อนที่จะบันทึกฉันพยายามเลือกจากตารางนี้และมันใช้งานได้การเชื่อมต่อกับ db

นี่คือวัตถุ Operator ของฉัน:

@Entity
public class Operator{

   @Id
   @GeneratedValue
   private Long id;

   private String username;

   private String password;


   private Integer active;

   //Getters and setters...
}

ในการบันทึกฉันใช้วิธีEntityManagerของJPApersist

นี่คือบันทึกบางส่วน:

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

อย่างที่ฉันเห็นปัญหาคือการกำหนดค่าด้วยการเพิ่มอัตโนมัติ แต่ฉันคิดไม่ออกว่าที่ไหน

ลองใช้เทคนิคบางอย่างที่ฉันเห็นที่นี่: ไฮเบอร์เนตไม่เคารพฟิลด์คีย์หลักของ MySQL auto_incrementแต่ก็ไม่ได้ผล

หากต้องการไฟล์การกำหนดค่าอื่น ๆ ฉันจะจัดเตรียมให้

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

คุณใช้ Hibernate เวอร์ชันใดอยู่
Steven Benitez

คำตอบ:


150

ในการใช้AUTO_INCREMENTคอลัมน์MySQL คุณควรใช้IDENTITYกลยุทธ์:

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

สิ่งที่คุณจะได้รับเมื่อใช้AUTOกับ MySQL:

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

ซึ่งเทียบเท่ากับ

@Id @GeneratedValue
private Long id;

กล่าวอีกนัยหนึ่งการทำแผนที่ของคุณควรใช้งานได้ แต่ไฮเบอร์เนตควรละเว้นidคอลัมน์ในคำสั่งแทรก SQL และไม่ใช่ ต้องมีชนิดที่ไม่ตรงกันที่ไหนสักแห่ง

คุณระบุภาษา MySQL ในการกำหนดค่าไฮเบอร์เนตของคุณหรือไม่ (อาจเป็น MySQL5InnoDBDialectหรือไม่หรือMySQL5Dialectขึ้นอยู่กับเครื่องยนต์ที่คุณใช้)

ใครเป็นคนสร้างตาราง? คุณสามารถแสดง DDL ที่สอดคล้องกันได้หรือไม่?

การติดตามผล:ฉันไม่สามารถจำลองปัญหาของคุณได้ โดยใช้รหัสของคุณนิติบุคคลและคุณ DDL, Hibernate สร้างดังต่อไปนี้ (คาดว่า) SQL กับ MySQL:

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

โปรดทราบว่าidคอลัมน์นี้ไม่อยู่ในข้อความข้างต้นตามที่คาดไว้

สรุปได้ว่ารหัสคำจำกัดความตารางและภาษาถิ่นของคุณถูกต้องและสอดคล้องกันควรใช้งานได้ หากไม่เหมาะสำหรับคุณอาจมีบางอย่างไม่ตรงกัน (ทำการสร้างใหม่ทั้งหมดตรวจสอบไดเร็กทอรีบิวด์อีกครั้ง ฯลฯ ) หรืออย่างอื่นผิดพลาด (ตรวจสอบบันทึกเพื่อหาสิ่งที่น่าสงสัย)

เกี่ยวกับภาษาถิ่นความแตกต่างเพียงอย่างเดียวระหว่างMySQL5Dialectหรือ MySQL5InnoDBDialectคือสิ่งที่เพิ่มENGINE=InnoDBเข้ามาในวัตถุตารางเมื่อสร้าง DDL การใช้อย่างใดอย่างหนึ่งไม่ได้เปลี่ยน SQL ที่สร้างขึ้น


Pascal คุณพูดถูก แต่มีบางอย่างในไฟล์ config ของฉันไม่ถูกต้อง ความหวานอื่น ๆ อาจเป็นไปได้ว่าตอนนี้ฉันได้ใส่ข้อมูลและไฟล์กำหนดค่าใหม่แล้วหรือยัง?
trivunm

9
@Pascal - ฉันพบว่าฉันต้องการ @GeneratedValue (strategy = GenerationType.IDENTITY) เพื่อให้ AUTO_INCREMENT ทำงานได้อย่างถูกต้องเมื่อใช้ JPA 2 / Hibernate 4.0.0.CR2 / JBoss AS 7 bit.ly/tdNyOJ
Joshua Davis

4
ทราบว่าเป็นจริงสำหรับMySQL ด้วยPostgreSQLคุณจะไม่ได้รับ@GeneratedValue(strategy=GenerationType.IDENTITY)เมื่อคุณเขียน@GeneratedValue(strategy=GenerationType.AUTO)และ@GeneratedValue. ดังนั้นระวังและพยายามที่จะฟุ่มเฟื่อย
sajjadG

หมายเหตุ: ด้วยเวอร์ชันล่าสุดของ Hibernate และ / หรือ MySQL / MariaDB GenerationType.AUTO จะใช้ค่าเริ่มต้นเป็น GenerationType.TABLE ซึ่งเมื่ออัปเกรดอาจนำไปสู่ปัญหาที่น่ารังเกียจเมื่อไม่ซิงค์ลำดับ
เข้ามาใน

อย่าลืมสร้างตารางใหม่: spring.jpa.hibernate.ddl-auto = create ด้วยการอัปเดตจะไม่ทำงาน
Glasnhost

38

การใช้ MySQL วิธีนี้ใช้ได้ผลกับฉันเท่านั้น:

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

อีก 2 แนวทางที่ปาสคาลระบุไว้ในคำตอบของเขาไม่ได้ผลสำหรับฉัน


ใช่ฉันตัดสินสิ่งนี้ในคำถาม / คำตอบของฉัน stackoverflow.com/questions/39675714/…
Yan Khonski

ขอบคุณมันทำงานสำหรับฉันฉันใช้JPAกับและspring-boot MySQL
Osama Al-Banna

12

สำหรับใครก็ตามที่อ่านสิ่งนี้ซึ่งใช้ EclipseLink สำหรับ JPA 2.0 ต่อไปนี้เป็นคำอธิบายประกอบสองรายการที่ฉันต้องใช้เพื่อรับ JPA เพื่อคงข้อมูลโดยที่ "MySequenceGenerator" คือชื่ออะไรก็ได้ที่คุณต้องการให้เครื่องกำเนิดไฟฟ้า "myschema" คือชื่อของ schema ในฐานข้อมูลของคุณที่มีวัตถุลำดับและ "mysequence" คือชื่อของวัตถุลำดับในฐานข้อมูล

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

สำหรับผู้ที่ใช้ EclipseLink (และอาจเป็นผู้ให้บริการ JPA อื่น ๆ ) เป็นเรื่องสำคัญที่คุณตั้งค่าแอ็ตทริบิวต์จัดสรรขนาดให้ตรงกับค่า INCREMENT ที่กำหนดไว้สำหรับลำดับของคุณในฐานข้อมูล หากไม่ทำเช่นนั้นคุณจะได้รับความล้มเหลวในการคงอยู่โดยทั่วไปและเสียเวลาไปกับการพยายามติดตามอย่างที่ฉันทำ นี่คือหน้าอ้างอิงที่ช่วยให้ฉันเอาชนะความท้าทายนี้:

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

นอกจากนี้เพื่อให้บริบทนี่คือสิ่งที่เราใช้:

Java 7 Glassfish 3.1 PostgreSQL 9.1 PrimeFaces 3.2 / JSF 2.1

นอกจากนี้เพื่อความขี้เกียจฉันสร้างสิ่งนี้ใน Netbeans ด้วยวิซาร์ดสำหรับการสร้างเอนทิตีจาก DB ตัวควบคุมจากเอนทิตีและ JSF จากเอนทิตีและวิซาร์ด (เห็นได้ชัด) ไม่ทราบวิธีจัดการกับคอลัมน์ ID ตามลำดับดังนั้น คุณจะต้องเพิ่มคำอธิบายประกอบเหล่านี้ด้วยตนเอง


6

โปรดตรวจสอบให้แน่ใจว่าประเภทข้อมูล id เป็น Long แทนที่จะเป็น String หากเป็นสตริงคำอธิบายประกอบ @GeneratedValue จะไม่ทำงานและ sql ที่สร้างขึ้นสำหรับ

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

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

ที่จำเป็นต้องเป็น

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

6

หากคุณใช้ Mysql กับ Hibernate v3 ก็ใช้ได้GenerationType.AUTOเพราะภายในจะใช้GenerationType.IDENTITYซึ่งเป็นวิธีที่เหมาะสมที่สุดสำหรับ MySQL

อย่างไรก็ตามใน Hibernate v5 มีการเปลี่ยนแปลง GenerationType.AUTOจะใช้GenerationType.TABLEสิ่งที่สร้างคำถามจำนวนมากสำหรับการแทรก

คุณสามารถหลีกเลี่ยงการใช้GenerationType.IDENTITY(ถ้า MySQL เป็นฐานข้อมูลเดียวที่คุณใช้) หรือด้วยสัญกรณ์เหล่านี้ (หากคุณมีหลายฐานข้อมูล):

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

ใช่สาเหตุที่ยุ่งยากสำหรับข้อผิดพลาดการถดถอยที่น่ารังเกียจเมื่ออัปเกรดแอปพลิเคชัน Spring ของคุณซึ่งภายใต้ฝากระโปรงอัปเกรดไฮเบอร์เนตด้วย
เข้า

1

ฉันพยายามทุกอย่าง แต่ก็ยังทำไม่ได้ฉันใช้ mysql, jpa กับ hibernate ฉันแก้ไขปัญหาของฉันโดยกำหนดค่า id 0 ในตัวสร้างต่อไปนี้คือรหัสประกาศ id ของฉัน

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

1

ในขณะที่คุณกำหนด id เป็นประเภท int ในการสร้างฐานข้อมูลคุณต้องใช้ชนิดข้อมูลเดียวกันในคลาสโมเดลด้วย และในขณะที่คุณกำหนด id เพื่อเพิ่มอัตโนมัติในฐานข้อมูลคุณต้องพูดถึงมันในคลาสโมเดลโดยส่งค่า 'GenerationType.AUTO' ลงในแอตทริบิวต์ 'strategy' ภายในคำอธิบายประกอบ @GeneratedValue จากนั้นรหัสจะกลายเป็นด้านล่าง

@Entity
public class Operator{

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

  private String username;

  private String password;

  private Integer active;

  //Getters and setters...
}

1

เช่นเดียวกับคำตอบ pascal หากคุณต้องการใช้. AUTO ด้วยเหตุผลบางประการคุณเพียงแค่เพิ่มคุณสมบัติแอปพลิเคชันของคุณ:

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

0

คุณสามารถตรวจสอบว่าคุณเชื่อมต่อกับฐานข้อมูลที่ถูกต้องหรือไม่ เนื่องจากฉันประสบปัญหาเดียวกัน แต่ในที่สุดฉันก็พบว่าฉันเชื่อมต่อกับฐานข้อมูลอื่น

ข้อมูลประจำตัว รองรับคอลัมน์เอกลักษณ์ใน DB2, MySQL, MS SQL Server, Sybase และ HypersonicSQL ตัวระบุที่ส่งคืนเป็นประเภท long สั้นหรือ int

ข้อมูลเพิ่มเติม: http://docs.jboss.org/hibernate/orm/3.5/reference/en/html/mapping.html#mapping-declaration-id


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.