如何使用JPA批注对MYSQL自动增量字段进行批注


105

直截了当,问题是将对象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...
}

为了节省,我使用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不尊重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?
史蒂文·贝尼特斯

Answers:


150

要使用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应该忽略idSQL插入语句中的列,事实并非如此。某处一定存在某种不匹配。

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

另外,谁创建了表格?您可以显示相应的DDL吗?

后续行动:我无法重现您的问题。使用的代码,你的实体,您的 DDL,Hibernate会与MySQL以下(预期)SQL:

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

请注意id,按预期,上述语句中没有该列。

综上所述,您的代码,表定义和方言是正确且一致的,应该可以使用。如果不适合您,则可能是某些内容不同步(执行干净的构建,仔细检查构建目录等)或其他错误(请检查日志中是否有可疑内容)。

关于方言,或 之间唯一的区别是后者在生成DDL时会添加到表对象中。使用一个或另一个不会更改生成的SQL。MySQL5DialectMySQL5InnoDBDialectENGINE=InnoDB


Pascal,您对此表示正确,但我的配置文件中的某些内容并不正确。既然我已经添加了新的信息和配置文件,也许还有其他建议吗?
trivunm

9
@Pascal-我发现我需要@GeneratedValue(strategy = GenerationType.IDENTITY)才能在使用JPA 2 / Hibernate 4.0.0.CR2 / JBoss AS 7时使AUTO_INCREMENT正常工作。bit.ly/ tdNyOJ
Joshua Davis

4
请注意,这对于MySQL是正确的。随着PostgreSQL的你没有得到@GeneratedValue(strategy=GenerationType.IDENTITY),当你写的@GeneratedValue(strategy=GenerationType.AUTO)@GeneratedValue。因此,请小心并尝试变得冗长。
sajjadG 2013年

注意:在较新版本的Hibernate和/或MySQL / MariaDB中,GenerationType.AUTO将默认为GenerationType.TABLE。升级时哪些会导致序列不同步而带来麻烦。
jwenting

不要忘记重新创建表:spring.jpa.hibernate.ddl-auto =创建。使用更新将无法正常工作
Glasnhost


12

对于正在使用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中使用用于从数据库生成实体,从实体生成控制器,以及从实体生成JSF的向导构建了NetBeans,这些向导(显然)不知道如何处理基于序列的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应用程序时棘手的原因会导致一些令人讨厌的回归错误,而该问题在后台也会升级Hibernate。
jwenting

5

请确保id数据类型为Long而不是String,如果它将为字符串,则@GeneratedValue批注将不起作用,并且为

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

1

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

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

1

在创建数据库时,您已经在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...
}

1

与pascal回答的相同,只是由于某种原因您需要使用.AUTO时,您只需要添加应用程序属性即可:

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.