【问题标题】:How to annotate MYSQL autoincrement field with JPA annotations如何使用 JPA 注释注释 MYSQL 自动增量字段
【发布时间】:2011-05-05 09:14:58
【问题描述】:

直截了当,问题是将对象运算符保存到 MySQL 数据库中。 在保存之前,我尝试从该表中进行选择,它可以正常工作,与 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 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`)
)

【问题讨论】:

  • 你使用的是什么版本的 Hibernate?

标签: java mysql orm jpa annotations


【解决方案1】:

要使用 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吗?

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

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

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

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

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

【讨论】:

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

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

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

Pascal 在他的回答中所说的其他 2 种方法对我不起作用。

【讨论】:

  • 是的,我在我的问题/答案中提到了这个。 stackoverflow.com/questions/39675714/…
  • 谢谢,它对我有用,我正在使用 JPAspring-bootMySQL
  • 同意这个答案,@GeneratedValue(strategy=GenerationType.AUTO) 和 MySQL 会产生一个额外的表 create table hibernate_sequence (next_val bigint) engine=InnoDB 来产生下一个 id。
【解决方案3】:

对于正在使用 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 玻璃鱼 3.1 PostgreSQL 9.1 PrimeFaces 3.2/JSF 2.1

另外,为了懒惰,我在 Netbeans 中使用向导构建了这个,用于从 DB 生成实体、从实体生成控制器和从实体生成 JSF,并且向导(显然)不知道如何处理基于序列的 ID列,因此您必须手动添加这些注释。

【讨论】:

    【解决方案4】:

    如果您在 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。
    【解决方案5】:

    如果是,请确保 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】:

      如果您使用 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/

      【讨论】:

        【解决方案7】:

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

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

        【讨论】:

          【解决方案8】:

          由于您在创建数据库时已将 id 定义为 int 类型,因此您也必须在模型类中使用相同的数据类型。由于您已将 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...
          }
          

          【讨论】:

            【解决方案9】:

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

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

            【讨论】:

              【解决方案10】:

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

              身份 支持 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

              【讨论】:

                猜你喜欢
                • 2016-07-21
                • 2013-11-27
                • 2017-12-18
                • 2011-12-07
                • 2017-06-19
                • 1970-01-01
                • 1970-01-01
                • 2010-11-03
                • 2019-02-22
                相关资源
                最近更新 更多