繁体   English   中英

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

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

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

    @Id
    @GeneratedValue
    private Long id;

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

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数据库有两条记录:

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

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

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

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

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

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

@GeneratedValue

注释,然后我总是要在插入之前找出数据库表中的下一个键是什么。

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

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

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

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

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

在我向表中注册新记录后,新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)

什么可能导致这个?

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

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

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

对于MySQL,您将能够成功地使用以下任何策略:

@GeneratedValue(strategy=GenerationType.AUTO)  

=>为主键指定auto_increment属性

@GeneratedValue(strategy=GenerationType.IDENTITY)

=>为主键指定auto_increment属性

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

Hibernate也有一代策略: native 它根据底层数据库的功能适当地选择生成策略。

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

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

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

并且在持久化时将其保留为null (0)

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

似乎SEQUENCE +指定了适合您的序列名称。

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

ALTER SEQUENCE RESTART WITH 13;

查看db以查找seq名称,例如:

ALTER SEQUENCE role_role_id_seq RESTART WITH 13;

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

希望能帮助到你 !

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM