Spring-Boot 2.0.0 似乎修改了 Hibernate 自动配置的方式。
让我们假设两个简单且独立的JPA实体:
@Entity
class Car {
@Id
@GeneratedValue
private long id;
//....
}
@Entity
class Airplane {
@Id
@GeneratedValue
private long id;
//....
}
之前,使用Spring-Boot 1.5.10 ,我能够生成单独的自动增量序列,这意味着我可以获得Car
1 作为主键,Airplane
1 作为主键。
它们之间没有相关性,例如没有共享序列。
现在,使用 2.0.0 ,当我按顺序创建第一个Car
然后第一个Airplane
时,汽车会 1 因为id和飞机得到 2 。
他似乎必须处理GeneratedType.AUTO
,即@GeneratedValue
注释来源中指定的“默认使用”。
但是,我的推理似乎停在此处,因为GeneratedType.AUTO
也被设置为 1.5.10 的默认设置。
实现我的期望的一个简单的解决方法是指定IDENTITY
生成策略类型,如下所示:
@Entity
class Car {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
//....
}
@Entity
class Airplane {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
//....
}
我无法弄清楚这种行为的解释。
什么使Spring-boot 2.0.0 发生变化,解释了这种情况?
答案 0 :(得分:12)
Spring Boot 2.0使用Hibernate 5.2(https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes)。
自5.2以来,Hibernate更改了其GeneratedType.AUTO
策略。任何本机不支持序列的数据库(例如MySQL)都使用TABLE生成器而不是IDENTITY。 (https://hibernate.atlassian.net/browse/HHH-11014)
这就是GeneratedType.AUTO
无法按预期工作的原因。
答案 1 :(得分:1)
正如安德鲁在评论中指出的那样,如果您不希望在其他表中创建值时增加ID,则可以这样指定ID:
@Id
@GeneratedValue(
strategy= GenerationType.AUTO,
generator="native"
)
@GenericGenerator(
name = "native",
strategy = "native"
)
private Long id;
这样做将使每个表具有以1,2,3 ...开头的唯一ID,以此类推。
答案 2 :(得分:0)
如果您需要一种快速且不合时宜的解决方案来防止此问题的发生:
spring.jpa.hibernate.use-new-id-generator-mappings=false
,如Spring Boot 2文档中所述:
spring.jpa.hibernate.use-new-id-generator-mappings= # Whether to use Hibernate's newer IdentifierGenerator for AUTO, TABLE and SEQUENCE.
这将阻止使用新的生成器,并保留Spring boot 1.x.x中包含的旧功能。
请注意,这可能不是最好的解决方案,但从短期来看非常有用
答案 3 :(得分:0)
您可以使用
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
使用MySQL自动增量。