We do pre-populate our IDs (custom strongly typed wrappers around UUID, e.g. UserId) so the generated code seems to think we have an update case of a detached entity, which is normally the only case when you really needmerge().
JavaDoc of EnityManager.merge():
Merge the state of the given entity into the current persistence context.
Expected behavior
Quarkus spring-data-jpa should only call merge() when really required, that is from my POV: merging a detached entity.
With a pre-populated id, the initial persist should be performed with persist(), not merge().
Actual behavior
Quarkus spring-data-jpa calls merge():
in a persist case when Id is pre-populated
in all update cases (Id is present)
To Reproduce
Steps to reproduce the behavior:
Will create a reproducer if required but I am pretty swamped right now.
Configuration
n/a
Screenshots
n/a
Environment (please complete the following information):
Output of uname -a or ver:
MINGW64_NT-10.0-18363 XXX 3.0.7-338.x86_64 2019-11-21 23:07 UTC x86_64 Msys
Output of java -version:
openjdk version "11.0.7" 2020-04-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.7+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.7+10, mixed mode)
GraalVM version (if different from Java): n/a
Quarkus version or git rev: 1.4.2.Final
Build tool (ie. output of mvnw --version or gradlew --version): Apache Maven 3.6.3
Option 1 is not an option for entities that use manually assigned identifiers
because the code clearly shows that the Id-check is skipped when a version column is present.
This would help in our case for the inital persist, but it would still use merge() for updates which means we might run into HHH-9362 and it would be "incorrect" since our entities are already attached when they are updated.
Alternatively, org.springframework.data.domain.Persistable.isNew() would also help, but again only for the intial persist. The interface is present in Quarkus spring-data-japa, but the method is not called.
What I am proposing here for the update case actually goes futher than what Spring is doing which might justify a configuration property to control that behaviour:
Only use merge() if EntityManager.contains() returns false.
Describe the bug Although we do not work with detached entities, we ran into https://hibernate.atlassian.net/browse/HHH-9362 and/or https://hibernate.atlassian.net/browse/HHH-11414 for a rather simple persist scenario. In the call stack we can see that the generated repository is calling
merge()
instead ofpersist()
. This is most likely due to this code inStockMethodsAdder
:We do pre-populate our IDs (custom strongly typed wrappers around
UUID
, e.g.UserId
) so the generated code seems to think we have an update case of a detached entity, which is normally the only case when you really needmerge()
. JavaDoc ofEnityManager.merge()
:Expected behavior Quarkus spring-data-jpa should only call
merge()
when really required, that is from my POV: merging a detached entity. With a pre-populated id, the initial persist should be performed withpersist()
, notmerge()
.Actual behavior Quarkus spring-data-jpa calls
merge()
:To Reproduce Steps to reproduce the behavior:
Configuration n/a
Screenshots n/a
Environment (please complete the following information):
uname -a
orver
:MINGW64_NT-10.0-18363 XXX 3.0.7-338.x86_64 2019-11-21 23:07 UTC x86_64 Msys
java -version
:1.4.2.Final
mvnw --version
orgradlew --version
):Apache Maven 3.6.3
Additional context The original
spring-data-jpa
is more or less doing the same, but it is also checking the value of the@Version
column: https://github.com/spring-projects/spring-data-jpa/blob/2.3.1.RELEASE/src/main/asciidoc/jpa.adoc#entity-state-detection-strategies See also:On a side note: I don't know why the docs say
because the code clearly shows that the Id-check is skipped when a version column is present.
This would help in our case for the inital persist, but it would still use
merge()
for updates which means we might run into HHH-9362 and it would be "incorrect" since our entities are already attached when they are updated.Alternatively,
org.springframework.data.domain.Persistable.isNew()
would also help, but again only for the intial persist. The interface is present in Quarkusspring-data-japa
, but the method is not called.What I am proposing here for the update case actually goes futher than what Spring is doing which might justify a configuration property to control that behaviour: Only use
merge()
ifEntityManager.contains()
returnsfalse
.https://github.com/quarkusio/quarkus/issues/10156
$upstream:10156$