Cách chú thích trường tự động gia tăng MYSQL với chú thích JPA


105

Đi thẳng vào vấn đề, vấn đề là lưu Toán tử đối tượng vào MySQL DB. Trước khi lưu, tôi cố gắng chọn từ bảng này và nó hoạt động, kết nối với db cũng vậy.

Đây là đối tượng Operator của tôi:

@Entity
public class Operator{

   @Id
   @GeneratedValue
   private Long id;

   private String username;

   private String password;


   private Integer active;

   //Getters and setters...
}

Để tiết kiệm, tôi sử dụng phương pháp EntityManagercủa JPA persist.

Đây là một số nhật ký:

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

Theo cách tôi thấy, vấn đề là cấu hình với tăng tự động nhưng tôi không thể tìm ra nơi.

Đã thử một số thủ thuật tôi đã thấy ở đây: Ngủ đông không tôn trọng trường khóa chính auto_increment của MySQL Nhưng không có gì trong số đó hoạt động

Nếu cần bất kỳ tệp cấu hình nào khác, tôi sẽ cung cấp chúng.

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

Bạn đang sử dụng phiên bản Hibernate nào?
Steven Benitez

Câu trả lời:


150

Để sử dụng một AUTO_INCREMENTcột MySQL , bạn phải sử dụng một IDENTITYchiến lược:

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

Đó là những gì bạn nhận được khi sử dụng AUTOvới MySQL:

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

Thực tế tương đương với

@Id @GeneratedValue
private Long id;

Nói cách khác, ánh xạ của bạn sẽ hoạt động. Nhưng Hibernate nên bỏ qua idcột trong câu lệnh chèn SQL, và không phải vậy. Ở đâu đó chắc hẳn có một kiểu không phù hợp.

Bạn đã chỉ định phương ngữ MySQL trong cấu hình Hibernate của mình chưa (có thể MySQL5InnoDBDialecthoặc MySQL5Dialecttùy thuộc vào công cụ bạn đang sử dụng)?

Ngoài ra, ai đã tạo ra bảng? Bạn có thể hiển thị DDL tương ứng không?

Tiếp theo: Tôi không thể tái tạo sự cố của bạn. Sử dụng mã của bạn tổ chức và bạn DDL, Hibernate tạo ra sau SQL (dự kiến) với MySQL:

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

Lưu ý rằng idcột không có trong câu lệnh trên, như mong đợi.

Tóm lại, mã của bạn, định nghĩa bảng và phương ngữ là chính xác và mạch lạc, nó sẽ hoạt động. Nếu nó không phù hợp với bạn, có thể có thứ gì đó không đồng bộ (tạo bản dựng sạch sẽ, kiểm tra kỹ thư mục bản dựng, v.v.) hoặc có gì đó khác chỉ là sai (kiểm tra nhật ký xem có bất kỳ điều gì đáng ngờ).

Về phương ngữ, sự khác biệt duy nhất giữa MySQL5Dialecthoặc MySQL5InnoDBDialectlà sau này thêm ENGINE=InnoDBvào các đối tượng bảng khi tạo DDL. Sử dụng cái này hay cái kia không thay đổi SQL được tạo.


Pascal, bạn nói đúng về điều đó nhưng có điều gì đó trong tệp cấu hình của tôi không đúng. Có thể có bất kỳ kích hoạt nào khác không, bây giờ tôi đã đặt thông tin và tệp cấu hình mới?
trivunm

9
@Pascal - Tôi thấy rằng tôi cần @GeneratedValue (chiến lược = GenerationType.IDENTITY) để AUTO_INCREMENT hoạt động bình thường khi sử dụng JPA 2 / Hibernate 4.0.0.CR2 / JBoss AS 7. bit.ly/tdNyOJ
Joshua Davis

4
Lưu ý rằng điều đó đúng với MySQL . Với PostgreSQL, bạn không nhận được @GeneratedValue(strategy=GenerationType.IDENTITY)khi viết @GeneratedValue(strategy=GenerationType.AUTO)@GeneratedValue. Vì vậy, hãy cẩn thận và cố gắng dài dòng.
sajjadG

lưu ý: với các phiên bản mới hơn của Hibernate và / hoặc MySQL / MariaDB GenerationType.AUTO sẽ mặc định là GenerationType.TABLE. Điều này khi nâng cấp có thể dẫn đến các vấn đề khó chịu với các chuỗi không đồng bộ.
jwenting

đừng quên tạo lại bảng: spring.jpa.hibernate.ddl-auto = create. Với bản cập nhật, nó sẽ không hoạt động
Glasnhost

38

Sử dụng MySQL, chỉ có phương pháp này hoạt động với tôi:

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

Hai cách tiếp cận khác được Pascal nêu trong câu trả lời của anh ấy không hiệu quả với tôi.


Vâng, tôi đã tham khảo điều này trong câu hỏi / câu trả lời của mình. stackoverflow.com/questions/39675714/…
Yan Khonski,

Cảm ơn, nó phù hợp với tôi, tôi đang sử dụng JPAvới spring-bootMySQL.
Osama Al-Banna

12

Đối với bất kỳ ai đang đọc bài này đang sử dụng EclipseLink cho JPA 2.0, đây là hai chú thích tôi phải sử dụng để lấy JPA duy trì dữ liệu, trong đó "MySequenceGenerator" là bất kỳ tên nào bạn muốn đặt cho trình tạo, "myschema" là tên của lược đồ trong cơ sở dữ liệu của bạn có chứa đối tượng chuỗi và "mysequence" là tên của đối tượng chuỗi trong cơ sở dữ liệu.

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

Đối với những người sử dụng EclipseLink (và có thể là các nhà cung cấp JPA khác), điều TIẾT DẠY là bạn đặt thuộc tính phân bổ kích thước để khớp với giá trị INCREMENT được xác định cho trình tự của bạn trong cơ sở dữ liệu. Nếu không, bạn sẽ nhận được một thất bại chung chung về sự bền bỉ và lãng phí rất nhiều thời gian để tìm ra nó, giống như tôi đã làm. Đây là trang tham khảo đã giúp tôi vượt qua thử thách này:

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

Ngoài ra, để cung cấp ngữ cảnh, đây là những gì chúng tôi đang sử dụng:

Java 7 Glassfish 3.1 PostgreSQL 9.1 PrimeFaces 3.2 / JSF 2.1

Ngoài ra, vì lợi ích của sự lười biếng, tôi đã xây dựng điều này trong Netbeans với các trình hướng dẫn để tạo Thực thể từ DB, Bộ điều khiển từ Thực thể và JSF từ Thực thể và các trình hướng dẫn (rõ ràng) không biết cách xử lý các cột ID dựa trên trình tự, vì vậy bạn sẽ phải thêm các chú thích này theo cách thủ công.


6

Nếu bạn đang sử dụng Mysql với Hibernate v3, bạn có thể sử dụng GenerationType.AUTOvì bên trong nó sẽ sử dụng GenerationType.IDENTITY, đây là cách tối ưu nhất cho MySQL.

Tuy nhiên trong Hibernate v5, Nó đã thay đổi. GenerationType.AUTOsẽ sử dụng GenerationType.TABLEmà tạo ra nhiều truy vấn cho việc chèn.

Bạn có thể tránh điều đó bằng cách sử dụng GenerationType.IDENTITY(nếu MySQL là cơ sở dữ liệu duy nhất bạn đang sử dụng) hoặc với các ký hiệu sau (nếu bạn có nhiều cơ sở dữ liệu):

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

vâng, nguyên nhân phức tạp cho một số lỗi hồi quy khó chịu khi nâng cấp ứng dụng Spring của bạn, ứng dụng này cũng nâng cấp Hibernate.
jwenting

5

Hãy đảm bảo rằng kiểu dữ liệu id là Dài thay vì Chuỗi, nếu đó sẽ là chuỗi thì chú thích @GeneratedValue sẽ không hoạt động và việc tạo sql cho

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

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

điều đó cần phải

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

1

Tôi đã thử mọi cách nhưng vẫn không thể làm được, tôi đang sử dụng mysql, jpa với chế độ ngủ đông, tôi đã giải quyết vấn đề của mình bằng cách gán giá trị id 0 trong hàm tạo Sau đây là mã khai báo id của tôi

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

1

Khi bạn đã xác định id trong kiểu int khi tạo cơ sở dữ liệu, bạn cũng phải sử dụng cùng một kiểu dữ liệu trong lớp mô hình. Và khi bạn đã xác định id để tăng tự động trong cơ sở dữ liệu, bạn phải đề cập đến nó trong lớp mô hình bằng cách chuyển giá trị 'GenerationType.AUTO' vào thuộc tính 'chiến lược' trong chú thích @GeneratedValue. Sau đó, mã sẽ trở thành như dưới đây.

@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

giống như pascal đã trả lời, chỉ cần bạn sử dụng .AUTO vì lý do nào đó, bạn chỉ cần thêm các thuộc tính ứng dụng của mình:

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

0

bạn có thể kiểm tra xem bạn đã kết nối với cơ sở dữ liệu chính xác chưa. vì tôi đã gặp phải vấn đề tương tự, nhưng cuối cùng tôi thấy rằng tôi đã kết nối với cơ sở dữ liệu khác nhau.

nhận dạng hỗ trợ các cột nhận dạng trong DB2, MySQL, MS SQL Server, Sybase và HypersonicSQL. Định danh trả về có kiểu long, short hoặc int.

Thông tin khác: http://docs.jboss.org/hibernate/orm/3.5/reference/en/html/mapping.html#mapping-decosystem-id


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.