Reputation: 2096
I have a basic SpringBoot 2.1.5.RELEASE app. Using Spring Initializer, JPA, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR file.
I have this domain class:
@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;
}
…
}
then I created this Junit method:
@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);
}
But I have an AssertionError, because it seems that for both objects id is 0:
java.lang.AssertionError: Values should be different. Actual: Purchase [id=0, txHash=null, shop=957]
Here the Shop:
@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>();
…
}
Upvotes: 0
Views: 8468
Reputation: 5512
From Spring 2.X.X RELEASE, spring-data-jpa
module using Hibernate5 version. If you explore the org.springframework.data:spring-data-jpa:2.1.5.RELEASE
pom.xml file you find out the version of hibernate dependency as
<hibernate>5.2.17.Final</hibernate>
The Hibernate version prior to Hibernate5 @GeneratedValue(strategy = GenerationType.IDENTITY)
works like a charm. But post Hibernate5 the following fix is necessary.
Duplicating my answer here for posterity.
@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
REASON
Excerpt from hibernate-issue
Currently, if the hibernate.id.new_generator_mappings is set to false, @GeneratedValue(strategy = GenerationType.AUTO) is mapped to native. If this property is true (which is the defult value in 5.x), the @GeneratedValue(strategy = GenerationType.AUTO) is always mapped to SequenceStyleGenerator.
For this reason, on any database that does not support sequences natively (e.g. MySQL) we are going to use the TABLE generator instead of IDENTITY.
However, TABLE generator, although more portable, uses a separate transaction every time a value is being fetched from the database. In fact, even if the IDENTITY disables JDBC batch updates and the TABLE generator uses the pooled optimizer, the IDENTITY still scales better.
Upvotes: 0
Reputation: 175
try changing the property mentioned below
spring.jpa.hibernate.use-new-id-generator-mappings=false
as new spring boot version 2.XX has changed this property to
spring.jpa.hibernate.use-new-id-generator-mappings=true
use below link for detailed understanding
Table 'DBNAME.hibernate_sequence' doesn't exist
Upvotes: 0
Reputation: 5703
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonProperty("id")
private Long id;
As you are using GenerationType IDENTITY, it means you are responsible for generating ID instead if hibernate.
If you want application will auto manage the id generation then use GenerationType Auto so update your GenerationType in Purchase as well as in Shop entity
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@JsonProperty("id")
private Long id;
...........................................................................
If you will still get error after above changes:
java.sql.SQLSyntaxErrorException: Table 'shops_db.hibernate_sequence' doesn't exist
By default, Hibernate generates key from hibernate_sequence table, we can disable it by setting this hibernate.use-new-id-generator-mappings to false.
spring.jpa.hibernate.use-new-id-generator-mappings=false
set this property in your application.properties
Upvotes: 2