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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38988757/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 03:59:34  来源:igfitidea点击:

How to auto generate primary key ID properly with Hibernate inserting records

javamysqldatabasehibernate

提问by user697911

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

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

    @Id
    @GeneratedValue
    private Long id;

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

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

insert into Member (id, name, email, phone_number) values (0, 'John Smith', '[email protected]', '2125551212')
insert into Member (id, name, email, phone_number) values (1, 'Mary Smith', '[email protected]', '2025551212') 

Now the MySql database has two records:

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

select * from Member;
+----+---------------------------+------------+--------------+
| id | email                     | name       | phone_number |
+----+---------------------------+------------+--------------+
|  0 | [email protected] | John Smith | 2125551212   |
|  1 | [email protected] | 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'

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.

我想这是因为自动生成的键总是以'1'开头,但在数据库中,它已经有两条记录,所以主键'1'会重复。

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?

有没有最好的方法来处理这种情况,这似乎很常见?

EDITED: As suggested, I used the Stragey:

编辑:按照建议,我使用了 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 |
+----+------------+---------+--------+

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

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

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)

What might cause this?

什么可能导致这种情况?

回答by amit

You should use IDENTITYgenerator. The IDENTITYgenerator 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.

你应该使用IDENTITY发电机。该IDENTITY发生器允许一个整数,BIGINT列是自动递增的需求。增量过程非常有效,因为它使用数据库内部轻量级锁定机制,而不是更重量级的事务性粗粒锁。

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

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

并且不要在插入语句中使用 id,因为它是自动生成的。
请注意, SEQUENCE 对您不起作用,因为 SEQUENCE 不适用于 MySQL

回答by Akash Mishra

For MySQL, you'll be able to successfully persist using any of the below mentioned strategies:

对于 MySQL,您将能够使用下面提到的任何策略成功持久化:

@GeneratedValue(strategy=GenerationType.AUTO)  

=> specify auto_increment attribute for primary key

=> 为主键指定 auto_increment 属性

@GeneratedValue(strategy=GenerationType.IDENTITY)

=>specify auto_increment attribute for primary key

=> 为主键指定 auto_increment 属性

On a further advanced usage, you can make use of TABLEstrategy GenerationType.TABLEwhere you can specify the primary key from a separate table and you can specify this table as @TableGenerator

在进一步的高级用法中,您可以使用TABLE策略GenerationType.TABLE,您可以在其中从单独的表中指定主键,并且可以将此表指定为@TableGenerator

Hibernate also has a generation strategy: native. It appropriately selects the generation strategy based upon the underlying database's capability.

Hibernate 还有一个生成策略:native. 它根据底层数据库的能力适当地选择生成策略。

回答by Priyanka Patil

<id name="id" column="id" type="integer"> 
    <generator class="increment"></generator> 
</id> 

In case if you are using mapping classes then just use above code to generate primary key automatically.

如果您正在使用映射类,那么只需使用上面的代码自动生成主键。

回答by user1568220

(postgresql) In the script where you populate the db add this at the end :

(postgresql) 在填充数据库的脚本中,在最后添加:

ALTER SEQUENCE RESTART WITH 13;

ALTER SEQUENCE RESTART 为 13;

look at the db to find the seq name, example :

查看数据库以查找序列名称,例如:

ALTER SEQUENCE role_role_id_seq RESTART WITH 13;

ALTER SEQUENCE role_role_id_seq RESTART WITH 13;

you should be able to name the generated sequence name as well with the anotation on the model...

您应该能够使用模型上的注释命名生成的序列名称......

hope it helps !

希望能帮助到你 !

回答by Deva

Now in Hibernate 5.2 you just need check @GeneratedValue(strategy = IDENTITY)at Variable level OR method level.

现在在 Hibernate 5.2 中,您只需要@GeneratedValue(strategy = IDENTITY)在变量级别或方法级别进行检查。

@Id
@GeneratedValue(strategy = IDENTITY)
private Integer id;

or

或者

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "Id", unique = true, nullable = false)

public Integer getId() {
    return this.id;
}

回答by Saurav Wahid

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

and you leave it null (0)when persisting.

null (0)当你坚持的时候你就离开了。

In some cases the AUTOstrategy is resolved to SEQUENCE rather than to IDENTITYor TABLE, so you might want to manually set it to IDENTITYor TABLE(depending on the underlying database).

在某些情况下,AUTO策略被解析为 SEQUENCE 而不是IDENTITYTABLE,因此您可能需要手动将其设置为IDENTITYTABLE(取决于底层数据库)。

It seems SEQUENCE + specifying the sequence name worked for you.

似乎 SEQUENCE + 指定序列名称对您有用。