Has Spring-boot changed the way auto-increment of ids works through @GeneratedValue?

39,883

Solution 1

Spring Boot 2.0 uses Hibernate 5.2 (https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes).
Hibernate changes its GeneratedType.AUTO strategy since 5.2. Any database that does not support sequences natively (e.g. MySQL), they use the TABLE generator instead of IDENTITY. (https://hibernate.atlassian.net/browse/HHH-11014)

That's why GeneratedType.AUTO does not work as you expected.

Solution 2

You can use

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

to use MySQL autoincrement.

Solution 3

As Andrew has pointed out in the comment, if you don't want the id to be incremented while values are created in other tables, you can specify your ID like this:

@Id
@GeneratedValue(
    strategy= GenerationType.AUTO,
    generator="native"
)
@GenericGenerator(
    name = "native",
    strategy = "native"
)
private Long id;

Doing this will make each table has its unique id beginning with 1,2,3 ... and so on.

Solution 4

If you are in need for a quick, not future-proof solution to prevent this issue from happening:

spring.jpa.hibernate.use-new-id-generator-mappings=false, as from the Spring Boot 2 docs:

spring.jpa.hibernate.use-new-id-generator-mappings= # Whether to use Hibernate's newer IdentifierGenerator for AUTO, TABLE and SEQUENCE.

This will prevent from using the new generators and keep the old functionality included in Spring boot 1.x.x.

Please note that this is probably not the best solution, but it is very helpful on short term

Share:
39,883
Admin
Author by

Admin

Updated on July 24, 2022

Comments

  • Admin
    Admin almost 2 years

    Spring-Boot 2.0.0 seems to have modified the way Hibernate is auto configured.

    Let's suppose two simple and independent JPA entities:

    @Entity
    class Car {
       @Id
       @GeneratedValue
       private long id;
       //....
    } 
    
    @Entity
    class Airplane {
       @Id
       @GeneratedValue
       private long id;
       //....
    }
    

    Prior, using Spring-Boot 1.5.10, I was able to generate separate sequences of auto-increments, meaning that I can get a Car with 1 as primary key and an Airplane with 1 as primary key too. No correlation between them, e.g no shared sequence.

    Now, with 2.0.0, when I sequentially create a very first Car then a very first Airplane, the car gets 1 as id and airplane gets 2.

    It seems that he has to deal with the GeneratedType.AUTO, that is the "used by default" specified within the @GeneratedValue annotation source.
    However, my reasoning seems to stop here since GeneratedType.AUTO was also set as default with the 1.5.10.

    A simple workaround to fulfil my expectation is to specify the IDENTITY strategy type of generation like so:

    @Entity
    class Car {
       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       private long id;
       //....
    } 
    
    @Entity
    class Airplane {
       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       private long id;
       //....
    }
    

    I can't figure out an explanation of this behavior.

    What has Spring-boot 2.0.0 changed, explaining this scenario?