In the excel_line_seq
sequence table the next_val
is 20
.
select * from excel_line_seq;
+----------+
| next_val |
+----------+
| 20 |
+----------+
But when I try to save a new entity with Spring Jpa repository, I see that id = 1
, after save()
invocation:
var excelLineEntity = new ExcelLineEntity();
excelLineEntity.setFileName("file1.txt");
excelLineEntity = excelLineRepository.save(excelLineEntity);
//actually it is not expected, id must be at least of value = 20 (or the next one)
Assertions.assertEquals(1, excelLineEntity.getId());
As a consequence, when I try to persist 2 entitites, I get the exception:
org.springframework.dao.DuplicateKeyException: A different object with the same identifier value was already associated with the session
Just because Spring Jpa Repository tries to use the same id = 1
for both independent entities.
Jpa entity is defined with strategy = GenerationType.SEQUENCE
for id:
@Entity
@Table(name = "excel_line")
public class ExcelLineEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
Long id;
String fileName;
Spring Data Jpa repository is used to persist enties:
public interface ExcelLineRepository extends JpaRepository<ExcelLineEntity, Long> {}
MySql has no true sequences support, so excel_line_seq
table is created and 20
is inserted as value
. MySql output is above.
Notes:
- the scheme is generated by liquibase
- the scheme is validated by Spring Jpa with:
spring.jpa.hibernate.ddl-auto=validate
property. The validation gets triggered. When the sequence table was not created, I got a validation error. So JPA definitely considers theexcel_line_seq
as the right table for id generation. - I tried to set explicitely sequence configuration as:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "excelLineSequence")
@SequenceGenerator(name = "excelLineSequence", sequenceName = "excel_line_seq", allocationSize = 50)
Long id;
But the result is the same.
What do I miss?
Must I explicitely calculate the next value from the sequence table to insert as id when I create a new entity? If the answer is yes, I must, then it sounds a bit strange.
Note: I am running integration tests, so it is not the case, when it happens with the running application and the next value might be stored by jpa.
1
I’m not sure if anyone will meet this issue again, it is very specific, but hope it might help someone, cause the bahaviour of jpa was mystical to me.
2 solutions were applied to make it function properly.
- The entity had not shown in the original question another field with
@ManyToOne
mapping configured:
@ManyToOne
@MapsId
@JoinColumn(name = "another_entity_id")
AnotherEntity anotherEntity;
And @MapsId
attribute somehow affected jpa id generation for ExcelLineEntity
.
I cannot explain it, why, and how at all it could be possible. But removing: @MapsId
fixed an issue with the same id generation by JPA for each new entity.
So the solution was to configure mapping as:
@ManyToOne
@JoinColumn(name = "another_entity_id")
AnotherEntity anotherEntity;
And it solved the problem.
Another issue was with the initial value for the sequence generation.
When I set it to 20:
select * from excel_line_seq;
+----------+
| next_val |
+----------+
| 20 |
+----------+
The new id were generated with -29, -28, etc. id values.
Setting the initial next_val
value to 1
, made the generation of id, beginnning from 1, 2, 3, etc.