SpringBoot 2.1.5.RELEASE & MySQL 8.0.15 中未生成 GenerationType.IDENTITY
Posted
技术标签:
【中文标题】SpringBoot 2.1.5.RELEASE & MySQL 8.0.15 中未生成 GenerationType.IDENTITY【英文标题】:GenerationType.IDENTITY not generated in SpringBoot 2.1.5.RELEASE & MySQL 8.0.15 【发布时间】:2019-10-03 13:01:28 【问题描述】:我有一个基本的 SpringBoot 2.1.5.RELEASE 应用程序。使用 Spring Initializer、JPA、嵌入式 Tomcat、Thymeleaf 模板引擎,并打包为可执行 JAR 文件。
我有这个域类:
@Entity
@Table(name="t_purchase")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Purchase implements Serializable
public Purchase()
public Purchase(Shop shop)
super();
this.shop = shop;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonProperty("id")
private Long id;
@JsonProperty("txHash")
private String txHash;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = “shop_id")
@JsonIgnore
Shop shop;
@Override
public boolean equals(Object o)
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Purchase purchase = (Purchase) o;
if (getTxHash()==null && purchase.getTxHash()==null)
return id == purchase.id;
else
return Objects.equals(getTxHash(), purchase.getTxHash());
@Override
public int hashCode()
int result = (int) (id ^ (id >>> 32));
result = 31 * result + Objects.hash(getTxHash());
return result;
…
然后我创建了这个 Junit 方法:
@Test
public void testFindByShopIdWithPurchases ()
Shop shop = new Shop ("Shop_NAME");
shopService.save(shop);
Purchase purchase1 = new Purchase(shop);
Purchase purchase2 = new Purchase(shop);
shop.getPurchases().add(purchase1);
shop.getPurchases().add(purchase2);
shopService.save(shop);
assertNotEquals (purchase1, purchase2);
但我有一个 AssertionError,因为这两个对象的 id 似乎都是 0:
java.lang.AssertionError: Values should be different. Actual: Purchase [id=0, txHash=null, shop=957]
这里是商店:
@Entity
@Table(name = “t_shop")
public class Shop implements Serializable
public Shop(String name)
this.name = name;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonProperty("id")
private Long id;
@JsonProperty("name")
private String name;
@OneToMany(mappedBy = “shop", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@JsonIgnore
private Set<Purchase> purchases = new HashSet<Purchase>();
…
【问题讨论】:
您的测试是否使用@Transactional
注释?如果没有,您可以尝试添加吗?
确实是:(
【参考方案1】:
从 Spring 2.X.X RELEASE,spring-data-jpa
模块使用 Hibernate5 版本。如果您浏览org.springframework.data:spring-data-jpa:2.1.5.RELEASE
pom.xml 文件,您会发现休眠依赖的版本为
<hibernate>5.2.17.Final</hibernate>
Hibernate5 @GeneratedValue(strategy = GenerationType.IDENTITY)
之前的 Hibernate 版本就像一个魅力。但是在发布 Hibernate5 之后,下面的fix 是必要的。
在此处复制我的answer 以供后代使用。
@Id
@GeneratedValue(strategy= GenerationType.AUTO,generator="native")
@GenericGenerator(name = "native",strategy = "native")
private Long id;
DDL
`id` BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY
原因
摘自hibernate-issue
目前,如果 hibernate.id.new_generator_mappings 设置为 false, @GeneratedValue(strategy = GenerationType.AUTO) 映射到本机。 如果此属性为真(这是 5.x 中的默认值),则 @GeneratedValue(strategy = GenerationType.AUTO) 始终映射到 序列样式生成器。
因此,在任何不支持序列的数据库上 本机(例如 mysql)我们将使用 TABLE 生成器 身份。
然而,TABLE 生成器虽然更便携,但使用单独的 每次从数据库中获取值时的事务。在 事实上,即使 IDENTITY 禁用 JDBC 批量更新和 TABLE 生成器使用池化优化器,IDENTITY 仍然可以更好地扩展。
【讨论】:
【参考方案2】:尝试更改下面提到的属性spring.jpa.hibernate.use-new-id-generator-mappings=false 由于新的 Spring Boot 版本 2.XX 已将此属性更改为spring.jpa.hibernate.use-new-id-generator-mappings=true 使用以下链接进行详细了解Table 'DBNAME.hibernate_sequence' doesn't exist
【讨论】:
【参考方案3】: @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonProperty("id")
private Long id;
当您使用 GenerationType IDENTITY 时,这意味着您负责在休眠时生成 ID。
如果您希望应用程序自动管理 id 生成,请使用 GenerationType Auto 所以在 Purchase 以及 Shop 实体
中更新您的 GenerationType @Id
@GeneratedValue(strategy = GenerationType.AUTO)
@JsonProperty("id")
private Long id;
.................................................. .....................
如果以上修改后还是报错:
java.sql.SQLSyntaxErrorException: Table 'shops_db.hibernate_sequence' doesn't exist
默认情况下,Hibernate 从 hibernate_sequence 表生成密钥,我们可以通过将 hibernate.use-new-id-generator-mappings 设置为 false 来禁用它。
spring.jpa.hibernate.use-new-id-generator-mappings=false
在您的 application.properties 中设置此属性
【讨论】:
【参考方案4】:将类型更改为 AUTO 为我解决了问题
【讨论】:
更改为 AUTO 时出现此错误:java.sql.SQLSyntaxErrorException: Table 'shops_db.hibernate_sequence' 不存在 请分享您的应用程序的 hibernate.ddl-auto 设置以上是关于SpringBoot 2.1.5.RELEASE & MySQL 8.0.15 中未生成 GenerationType.IDENTITY的主要内容,如果未能解决你的问题,请参考以下文章
@OneToMany Spring Boot 2.1.5.RELEASE 中的 Spring Data JPA 没有获取所有数据
Spring Boot2(002):手动创建第1个SpringBoot2简单应用——“HelloWorld” web 工程