ChatGPT解决这个技术问题 Extra ChatGPT

如何使用 JPA 注释注释 MYSQL 自动增量字段

直截了当,问题是将对象运算符保存到 MySQL 数据库中。在保存之前,我尝试从该表中进行选择并且它有效,与数据库的连接也是如此。

这是我的运算符对象:

@Entity
public class Operator{

   @Id
   @GeneratedValue
   private Long id;

   private String username;

   private String password;


   private Integer active;

   //Getters and setters...
}

为了节省,我使用 JPA EntityManagerpersist 方法。

这是一些日志:

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

我看到它的方式,问题是配置自动增量,但我不知道在哪里。

尝试了一些我在这里看到的技巧:Hibernate not respecting MySQL auto_increment primary key field 但没有任何效果

如果需要任何其他配置文件,我会提供。

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`)
)
你用的是什么版本的休眠?

P
Pascal Thivent

要使用 MySQL AUTO_INCREMENT 列,您应该使用 IDENTITY 策略:

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

AUTO 与 MySQL 一起使用时,您会得到以下结果:

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

这实际上相当于

@Id @GeneratedValue
private Long id;

换句话说,您的映射应该可以工作。但是 Hibernate 应该省略 SQL 插入语句中的 id 列,而事实并非如此。一定有某种不匹配的地方。

您是否在 Hibernate 配置中指定了 MySQL 方言(可能是 MySQL5InnoDBDialectMySQL5Dialect,具体取决于您使用的引擎)?

另外,谁创建了这张桌子?你能显示相应的DDL吗?

跟进:我无法重现您的问题。使用您的实体和 DDL 的代码,Hibernate 使用 MySQL 生成以下(预期的)SQL:

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

请注意,如预期的那样,上述语句中没有 id 列。

总而言之,您的代码、表格定义和方言是正确且连贯的,它应该可以工作。如果它不适合您,则可能某些内容不同步(进行干净的构建,仔细检查构建目录等)或其他错误(检查日志是否有任何可疑内容)。

关于方言,MySQL5DialectMySQL5InnoDBDialect之间的唯一区别在于后者在生成DDL时将ENGINE=InnoDB添加到表对象中。使用其中一种不会更改生成的 SQL。


帕斯卡,你是对的,但我的配置文件中的某些内容是不正确的。既然我已经放置了新的信息和配置文件,可能还有其他建议吗?
@Pascal - 我发现在使用 JPA 2 / Hibernate 4.0.0.CR2 / JBoss AS 7 时,我需要 @GeneratedValue(strategy=GenerationType.IDENTITY) 让 AUTO_INCREMENT 正常工作。bit.ly/tdNyOJ
请注意,MySQL 也是如此。在 PostgreSQL 中,您在编写 @GeneratedValue(strategy=GenerationType.AUTO)@GeneratedValue 时不会得到 @GeneratedValue(strategy=GenerationType.IDENTITY)。所以要小心,尽量冗长。
注意:使用更新版本的 Hibernate 和/或 MySQL/MariaDB GenerationType.AUTO 将默认为 GenerationType.TABLE 。升级时可能会导致不同步序列的严重问题。
不要忘记重新创建表:spring.jpa.hibernate.ddl-auto = create。使用更新将无法正常工作
S
Sнаđошƒаӽ

使用 MySQL,只有这种方法对我有用:

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

帕斯卡在他的回答中所说的其他两种方法对我不起作用。


是的,我在我的问题/答案中提到了这一点。 stackoverflow.com/questions/39675714/…
谢谢,它对我有用,我将 JPAspring-bootMySQL 一起使用。
同意这个答案,使用 MySQL 的 @GeneratedValue(strategy=GenerationType.AUTO) 将产生一个额外的表 create table hibernate_sequence (next_val bigint) engine=InnoDB 来产生下一个 id。
M
Max Awesome

对于正在使用 EclipseLink for JPA 2.0 阅读本文的任何人,这里是我必须用来让 JPA 持久化数据的两个注释,其中“MySequenceGenerator”是您想给生成器起的任何名称,“myschema”是数据库中包含序列对象的模式,“mysequence”是数据库中序列对象的名称。

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

对于那些使用 EclipseLink(可能还有其他 JPA 提供程序)的用户,将 allocationSize 属性设置为与数据库中为您的序列定义的 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 列,所以您必须手动添加这些注释。


d
dmarquina

如果您在 Hibernate v3 中使用 Mysql,则可以使用 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 应用程序时一些令人讨厌的回归错误的棘手原因,它在引擎盖下也升级了 Hibernate。
A
ABHAY JOHRI

请确保 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))

A
Adel

如果您使用的是 MariaDB,这将起作用

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

更多信息,您可以查看https://thorben-janssen.com/hibernate-tips-use-auto-incremented-column-primary-key/


M
M. Waseem Ullah Khan

我尝试了每件事,但仍然无法做到这一点,我正在使用mysql,jpa和hibernate,我通过在构造函数中分配id 0的值来解决我的问题以下是我的id声明代码

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

R
Robert

由于您在创建数据库时已在 int 类型中定义了 id,因此您也必须在模型类中使用相同的数据类型。并且由于您已将 id 定义为在数据库中自动递增,因此您必须通过将值“GenerationType.AUTO”传递到注释 @GeneratedValue 中的属性“strategy”中来在模型类中提及它。然后代码变成如下。

@Entity
public class Operator{

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

  private String username;

  private String password;

  private Integer active;

  //Getters and setters...
}

J
Jorge

与帕斯卡回答的相同,只是如果您出于某种原因需要使用 .AUTO ,您只需要添加您的应用程序属性:

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

M
Mohan Reddy

你能检查你是否连接到正确的数据库。因为我遇到了同样的问题,但最后我发现我连接到不同的数据库。

identity 支持 DB2、MySQL、MS SQL Server、Sybase 和 HypersonicSQL 中的标识列。返回的标识符是 long、short 或 int 类型。

更多信息:http://docs.jboss.org/hibernate/orm/3.5/reference/en/html/mapping.html#mapping-declaration-id