我有一个成员实体类,其主键定义为:
@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
注释,然后我总是要在插入之前找出数据库表中的下一个键是什么。
有没有最好的方法来处理这种情况,这似乎很常见?
EDITED: 正如所建议的那样,我使用了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)
可能是什么原因引起的?
答案 0 :(得分:7)
您应该使用IDENTITY
生成器。 IDENTITY
生成器允许整数和bigint列按需自动递增。增量过程非常有效,因为它使用数据库内部轻量级锁定机制,而不是更重量级的事务过程 - 粒度锁。
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
并且不要在insert语句中使用id,因为它是自动生成的 请注意,SEQUENCE不适合您,因为SEQUENCE不适用于MySQL
答案 1 :(得分:1)
对于MySQL,您将能够成功地使用以下任何一种策略:
@GeneratedValue(strategy=GenerationType.AUTO)
=>为主键指定auto_increment属性
@GeneratedValue(strategy=GenerationType.IDENTITY)
=>指定主键的auto_increment属性
在进一步的高级用法中,您可以使用TABLE
策略GenerationType.TABLE,您可以在其中指定单独表中的主键,并可以将此表指定为@TableGenerator
Hibernate还有一个生成策略:native
。它根据底层数据库的功能适当地选择生成策略。
答案 2 :(得分:1)
<id name="id" column="id" type="integer">
<generator class="increment"></generator>
</id>
如果您正在使用映射类,那么只需使用上面的代码自动生成主键。
答案 3 :(得分:0)
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
并在保留时保留null (0)
。
在某些情况下,AUTO
策略已解析为SEQUENCE而不是IDENTITY
或TABLE
,因此您可能需要手动将其设置为IDENTITY
或TABLE
(取决于底层数据库)。
似乎SEQUENCE +指定了适合您的序列名称。
答案 4 :(得分:0)
(postgresql)在填充数据库的脚本中,在最后添加:
ALTER SEQUENCE RESTART WITH 13;
查看db以查找seq名称,例如:
ALTER SEQUENCE role_role_id_seq RESTART WITH 13;
您应该能够使用模型上的anotation命名生成的序列名称......
希望它有所帮助!答案 5 :(得分:0)
现在,在Hibernate 5.2中,您只需要在变量级别或方法级别检查@GeneratedValue(strategy = IDENTITY)
。
@Id
@GeneratedValue(strategy = IDENTITY)
private Integer id;
或
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "Id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}