J.R
J.R

Reputation: 2163

Springboot 2 CrudRepository.save always throws ConstraintViolationException

I have Migrated the Springboot version from 1.4.3.RELEASE to 2.1.0.RELEASE in my project. After that CrudRepository.save() always throws org.hibernate.exception.ConstraintViolationException: could not execute statement.

This is what I can see in the Logs :

o.h.e.j.s.SqlExceptionHelper[m: SQL Error: 1062, SQLState: 23000
o.h.e.j.s.SqlExceptionHelper[m: Duplicate entry '11' for key 'PRIMARY'
o.h.i.ExceptionMapperStandardImpl[m: HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement

This is the entity I am trying to save.

@Getter
@Setter
@Entity
@Table(name = "project_m")
public class Project {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    private Long id;

    @Column(name = "name" , nullable = false)
    private String name;

    //other fields

}

Upvotes: 0

Views: 3063

Answers (3)

SAMUEL
SAMUEL

Reputation: 8562

ConstraintViolationException occurred due to the fact that your primary key constraint for SQL database violates In SQL the primary key is a unique key to identify the record, the database will throw an exception when you trying to insert a duplicate value to a primary column. which in turn got by the hibernate and passed to your code and is the reason for this exception.

From Springboot 1.4.3.RELEASE to 2.1.0.RELEASE Hibernate version is updated from 5.0 to 5.3.

The way Hibernate interprets AUTO generation type has changed starting with Hibernate version 5.0

If you use strategy="AUTO", Hibernate will generate a table called hibernate_sequence to provide the next number for the ID sequence. You may have forgotten to add the AutoIncrement feature to your table's PK.

Another way to fix is use following annotations with strategy="AUTO"

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

You may use generation strategy strategy="IDENTITY" to enforce using the AutoIncrement feature available in SQL and avoid creating a table.

Pls check here to get some more insights

Upvotes: 2

J.R
J.R

Reputation: 2163

I got a workaround for this issue by setting a large value in hibernate_sequence table. I saw that the primary key value from the duplicate primary key error is generated from a table named hibernate_sequence.

When we set GenerationType.AUTO in the entity,Hibernate selects the generation strategy based on the Hibernate dialect. In older versions , Hibernate selected the GenerationType.IDENTITY as default for MySQL databases.

It now selects the GenerationType.TABLE which uses a database table to generate primary keys

Upvotes: 1

Deepthi
Deepthi

Reputation: 545

What has changed from Springboot 1.4.3.RELEASE to 2.1.0.RELEASE is the internal Hibernate version from 5.0 to 5.3.

And what has changed in this is the way the SequenceGenerator works, which is used in case the strategy is GenerationType.AUTO (as is in your case). enter image description here

Link to hibernate migration doc here.

More details on hibernate generation strategy here.

My guess is there are 2 parallel sessions inserting into this table, and both of them now share a local copy of the sequence number, which creates this collision. Not sure though!

My suggestion would be to change the strategy to GenerationType.SEQUENCE and try.

Upvotes: 3

Related Questions