我有一个基本的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>();
…
}
答案 0 :(得分:0)
将类型更改为AUTO可以为我解决问题
答案 1 :(得分:0)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonProperty("id")
private Long id;
在使用GenerationType IDENTITY 时,这意味着您应负责生成ID(如果处于休眠状态)。
如果您希望应用程序自动管理ID生成,请使用GenerationType 自动 因此,请在购买和商店实体
中更新您的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中设置此属性
答案 2 :(得分:0)
尝试更改下面提到的属性
spring.jpa.hibernate.use-new-id-generator-mappings = false
由于新的春季启动版本2.XX已将此属性更改为
spring.jpa.hibernate.use-new-id-generator-mappings = true
使用下面的链接进行详细了解
Table 'DBNAME.hibernate_sequence' doesn't exist
答案 3 :(得分:0)
从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.id.new_generator_mappings设置为false, @GeneratedValue(strategy = GenerationType.AUTO)映射到本机。 如果此属性为true(这是5.x中的defult值),则 @GeneratedValue(strategy = GenerationType.AUTO)始终映射到 SequenceStyleGenerator。
因此,在任何不支持序列的数据库上 本机(例如MySQL),我们将改为使用TABLE生成器 身份。
但是,TABLE生成器虽然更便于移植,但却使用了单独的 每次从数据库中获取值时进行事务处理。在 实际上,即使IDENTITY禁用了JDBC批处理更新和TABLE, 生成器使用池优化器,IDENTITY的伸缩性仍然更好。