如何使用Hibernate插入记录正确自动生成主键ID

如何使用Hibernate插入记录正确自动生成主键ID

问题描述:

我有一个成员实体类,其主键定义为:

I have a Member entity class whose primary key is defined as:

    @Id
    @GeneratedValue
    private Long id;

启动应用程序时,我使用Hibernate将两个记录预加载到数据库中:

I pre-loaded two records into database with Hibernate when I starts the application:

insert into Member (id, name, email, phone_number) values (0, 'John Smith', 'john.smith@mailinator.com', '2125551212')
insert into Member (id, name, email, phone_number) values (1, 'Mary Smith', 'mary.smith@mailinator.com', '2025551212') 

现在MySql数据库有两个记录:

Now the MySql database has two records:

select * from Member;
+----+---------------------------+------------+--------------+
| id | email                     | name       | phone_number |
+----+---------------------------+------------+--------------+
|  0 | john.smith@mailinator.com | John Smith | 2125551212   |
|  1 | mary.smith@mailinator.com | Mary Smith | 2025551212   |

+ ---- + --------------- ------------ + ------------ + -------------- +

+----+---------------------------+------------+--------------+

现在,在我的会员注册页面中,当我提交注册新会员的请求时,我收到以下错误消息:

Now, in my member registration page, when I submit a request to register a new member, I received this error message:

Caused by: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'

我认为是因为自动生成的密钥始终以 1开头,但是在数据库中,它已经有两个记录,因此主键 1将重复。

I figured that it because the auto-generated key always starts with '1', but in the database, it already has two records, so the primary key '1' will be duplicate.

我的问题是,鉴于表中已有许多记录,如何正确创建主键?如果我不使用

My question is, how to create the primary key properly, given a number of existing records in the table? If I don't use the

@GeneratedValue

注释,那么在插入之前,我总是必须从数据库表中找出下一个键。

annotation, then I always have to find out what's the next key from the database table before insertion.

解决这种情况的最佳方法,这似乎很常见?

Is there a best way to handle this situation, which seems very common?

编辑:
正如建议的那样,我使用了Stragey:

EDITED: As suggested, I used the Stragey:

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

奇怪的是,如果表中有两个现有记录,如下所示:

What's strange is that, if there are two existing records in the table as below:

select * from English;
+----+------------+---------+--------+
| id | sentence   | source  | status |
+----+------------+---------+--------+
|  1 | i love you | unknown |      0 |
|  2 | i like you | unknown |      0 |
+----+------------+---------+--------+

在表中注册新记录后,新ID以4开头,而不是3,如下所示。

after I register a new record into the table, the new ID starts with 4, not 3, as below.

select * from English;
+----+----------------+---------+--------+
| id | sentence       | source  | status |
+----+----------------+---------+--------+
|  1 | i love you     | unknown |      0 |
|  2 | i like you     | unknown |      0 |
|  4 | I have a book. | Unknown |      0 |
+----+----------------+---------+--------+
3 rows in set (0.00 sec)

这可能是什么原因?

您应使用 IDENTITY 生成器。 IDENTITY 生成器允许按需自动增加integer和bigint列。增量过程非常有效,因为它使用了数据库内部的轻量级锁定机制,而不是重量级的事务性过程粒度锁定。

You should use IDENTITY generator. The IDENTITY generator allows an integer and bigint column to be auto-incremented on demand. The increment process is very efficient since it uses a database internal lightweight locking mechanism as opposed to the more heavyweight transactional course-grain locks.

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

也不要在插入语句中使用id,因为它会自动生成。

请注意,SEQUENCE不适用于您,因为SEQUENCE不适用于MySQL

And don't use id in the insert statement as it is being generated automatically.
Note that SEQUENCE will not work for you as SEQUENCE does not work with MySQL