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

时间:2010-11-04 23:51:10

标签: java mysql orm jpa annotations

直截了当,问题是将对象操作员保存到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 EntityManager的{​​{1}}方法。

这是一些日志:

persist

我看到它的方式,问题是配置有自动增量,但我无法弄清楚在哪里。

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

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

DDL:

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

10 个答案:

答案 0 :(得分:126)

要使用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 insert语句中的id列,而不是。某处肯定会有一种不匹配。

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

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

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

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

请注意,正如预期的那样,上述语句中不存在id列。

总而言之,您的代码,表格定义和方言是正确和连贯的,它应该有效。如果它不适合你,也许某些东西不同步(做一个干净的构建,仔细检查构建目录等)或其他东西是错误的(检查日志中是否有任何可疑的东西)。

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

答案 1 :(得分:30)

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

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

帕斯卡尔在答案中提出的另外两种方法并不适用于我。

答案 2 :(得分: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中构建了这个用于从DB生成实体,从实体生成控制器,从实体生成JSF的向导,并且向导(显然)不知道如何处理基于序列的ID列,因此您必须手动添加这些注释。

答案 3 :(得分: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))

答案 4 :(得分:1)

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__APPLE__)
#  define COMMON_DIGEST_FOR_OPENSSL
#  include <CommonCrypto/CommonDigest.h>
#  define SHA1 CC_SHA1
#else
#  include <openssl/md5.h>
#endif

char *str2md5(const char *str, int length) {
   int n;
   MD5_CTX c;
   unsigned char digest[16];
   char *out = (char*)malloc(33);

   MD5_Init(&c);

   while (length > 0) {
        if (length > 512) {
            MD5_Update(&c, str, 512);
        } else {
            MD5_Update(&c, str, length);
        }
        length -= 512;
        str += 512;
     }

     MD5_Final(digest, &c);

     for (n = 0; n < 16; ++n) {
     snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int)digest[n]);
     }

    return out;
 }

   int main(int argc, char **argv) {
       char *output = str2md5("hello", strlen("hello"));
       printf("%s\n", output);
       free(output);
        return 0;
    }

答案 5 :(得分:1)

如果您将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")

答案 6 :(得分:1)

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

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

答案 7 :(得分:1)

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

答案 8 :(得分:0)

我尝试了所有的东西,但我仍然无法做到这一点,我使用mysql,jpa与hibernate,我通过在构造函数中赋值id 0解决了我的问题 以下是我的id声明代码

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

答案 9 :(得分:0)

可以检查是否连接到正确的数据库。因为我遇到了同样的问题,但最终我发现我连接到了另一个数据库。

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