Nuñito Calzada
Nuñito Calzada

Reputation: 2096

GenerationType.IDENTITY not generated in SpringBoot 2.1.5.RELEASE & MySQL 8.0.15

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

Answers (4)

Prasanth Rajendran
Prasanth Rajendran

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

Sahil Bhalla
Sahil Bhalla

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

Bhushan Uniyal
Bhushan Uniyal

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

m-2127
m-2127

Reputation: 161

Changing the type to AUTO solved the problem for me

Upvotes: 0

Related Questions