I have to override/update a set of existing entities mapped by a cascade @OneToMany relationship from another class.
I would like to avoid having to previously load the existing entities and then save them
for making them attached to the session.
@Data
@Entity
@Table(name = "my_asset")
public class MyAsset {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@OneToMany(mappedBy = "myAsset",
fetch = FetchType.EAGER,
cascade = {CascadeType.ALL},
orphanRemoval = true)
private List<AssetComponent> components = new ArrayList<>();
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Entity
@SelectBeforeUpdate
@DynamicUpdate
@Table(name = "asset_component")
public class AssetComponent {
@Id
@EqualsAndHashCode.Include
private UUID id;
@Column(name = "model_id", nullable = false)
private UUID modelID;
@Column(nullable = false)
private String type;
@Column(nullable = false)
private String name;
@ManyToOne(optional = false)
@OnDelete(action = OnDeleteAction.CASCADE)
private MyAsset myAsset;
}
@Repository
public interface MyAssetRepository extends JpaRepository<MyAsset, Long> {}
Now, if I have an existing MyAsset with some existing components already in the DB, I cannot save the MyAsset directly:
MyAsset myAsset = new MyAsset();
myAsset.setComponents(Collections.singletonList(AssetComponent.builder()
.id(UUID.fromString("b76d8a3b-2f0c-442a-bf50-58a19fce0fc9"))
.modelID(UUID.fromString("22db9474-eeeb-4007-91a8-3e8bdfa9b83a"))
.name("Component A")
.type("Type A")
.myAsset(myAsset)
.build()));
myAssetRepository.save(myAsset);
because it gives me a stack of exceptions about the duplicate key exception with the AssetComponent ID:
org.springframework.dao.DataIntegrityViolationExceptionorg.hibernate.exception.ConstraintViolationExceptionorg.postgresql.util.PSQLException
How can I make the MyAsset & AssetComponent @Repository automatically merge the existing entities (if they have the same id) even if they have not been previously loaded from the DB?
Update
I created a GitHub repository to show you the minimum not working example: https://github.com/MaurizioCasciano/Spring-Data-JPA-Testing
I slightly changed the entities' name to make them as much general as possible: Container 1 --> N Item
I also enabled as much debugging as possible (at least i think so. Let me know if I can show more debugging info) using these properties:
spring:
datasource:
url: jdbc:h2:mem:test
driver-class-name: org.h2.Driver
username: test
password: test
h2:
console:
enabled: true
path: /h2-console
jpa:
database-platform: org.hibernate.dialect.H2Dialect
properties:
hibernate:
show_sql: true
format_sql: true
use_sql_comments: true
logging:
level:
org.hibernate.type: trace
This is the simple @Test I'm running:
@SpringBootTest
public class ContainerRepositoryTests {
@Autowired
private ContainerRepository containerRepository;
@Test
public void testSaveContainer(){
final UUID containerID = UUID.randomUUID();
Container container = new Container();
container.setId(containerID);
Collection<Item> items = new HashSet<>();
final UUID itemID = UUID.randomUUID();
Item item = new Item();
item.setId(itemID);
item.setContainer(container);
items.add(item);
container.setItems(items);
this.containerRepository.save(container);
this.containerRepository.save(container);
}
}
and it results in the following console output:
Hibernate:
drop table if exists container CASCADE
Hibernate:
drop table if exists container_items CASCADE
Hibernate:
drop table if exists item CASCADE
Hibernate:
create table container (
id binary(255) not null,
primary key (id)
)
Hibernate:
create table container_items (
container_id binary(255) not null,
items_id binary(255) not null
)
Hibernate:
create table item (
id binary(255) not null,
container_id binary(255) not null,
primary key (id)
)
Hibernate:
alter table container_items
add constraint UK_tjc4gid6ob0h8pqhc9f4s1u9k unique (items_id)
Hibernate:
alter table container_items
add constraint FK3jaf77lxfykpono42ak2pqh7p
foreign key (items_id)
references item
Hibernate:
alter table container_items
add constraint FKt1xy6gjb3c94t8ifnjp36hsol
foreign key (container_id)
references container
Hibernate:
alter table item
add constraint FK9b9sc6vhhyquxqbixmhqtx0g
foreign key (container_id)
references container
Hibernate:
/* load org.testing.spring.data.jpa.domain.Container */ select
container0_.id as id1_0_1_,
items1_.container_id as containe1_1_3_,
item2_.id as items_id2_1_3_,
item2_.id as id1_2_0_,
item2_.container_id as containe2_2_0_
from
container container0_
left outer join
container_items items1_
on container0_.id=items1_.container_id
left outer join
item item2_
on items1_.items_id=item2_.id
where
container0_.id=?
2022-06-10 09:36:41.066 TRACE 12924 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BINARY] - [b8718f19-8a5c-480a-bcb4-a116a74a0fd0]
Hibernate:
/* load org.testing.spring.data.jpa.domain.Item */ select
item0_.id as id1_2_0_,
item0_.container_id as containe2_2_0_
from
item item0_
where
item0_.id=?
2022-06-10 09:36:41.100 TRACE 12924 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BINARY] - [63050373-8b6b-4fca-8ead-49319ee0c1bb]
Hibernate:
/* insert org.testing.spring.data.jpa.domain.Container
*/ insert
into
container
(id)
values
(?)
2022-06-10 09:36:41.121 TRACE 12924 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BINARY] - [b8718f19-8a5c-480a-bcb4-a116a74a0fd0]
Hibernate:
/* insert org.testing.spring.data.jpa.domain.Item
*/ insert
into
item
(container_id, id)
values
(?, ?)
2022-06-10 09:36:41.124 TRACE 12924 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BINARY] - [b8718f19-8a5c-480a-bcb4-a116a74a0fd0]
2022-06-10 09:36:41.125 TRACE 12924 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BINARY] - [63050373-8b6b-4fca-8ead-49319ee0c1bb]
Hibernate:
/* insert collection
row org.testing.spring.data.jpa.domain.Container.items */ insert
into
container_items
(container_id, items_id)
values
(?, ?)
2022-06-10 09:36:41.128 TRACE 12924 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BINARY] - [b8718f19-8a5c-480a-bcb4-a116a74a0fd0]
2022-06-10 09:36:41.128 TRACE 12924 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BINARY] - [63050373-8b6b-4fca-8ead-49319ee0c1bb]
Hibernate:
/* load org.testing.spring.data.jpa.domain.Container */ select
container0_.id as id1_0_1_,
items1_.container_id as containe1_1_3_,
item2_.id as items_id2_1_3_,
item2_.id as id1_2_0_,
item2_.container_id as containe2_2_0_
from
container container0_
left outer join
container_items items1_
on container0_.id=items1_.container_id
left outer join
item item2_
on items1_.items_id=item2_.id
where
container0_.id=?
2022-06-10 09:36:41.134 TRACE 12924 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BINARY] - [b8718f19-8a5c-480a-bcb4-a116a74a0fd0]
Hibernate:
/* load org.testing.spring.data.jpa.domain.Item */ select
item0_.id as id1_2_0_,
item0_.container_id as containe2_2_0_
from
item item0_
where
item0_.id=?
2022-06-10 09:36:41.137 TRACE 12924 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BINARY] - [63050373-8b6b-4fca-8ead-49319ee0c1bb]
Hibernate:
/* insert org.testing.spring.data.jpa.domain.Container
*/ insert
into
container
(id)
values
(?)
2022-06-10 09:36:41.138 TRACE 12924 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BINARY] - [b8718f19-8a5c-480a-bcb4-a116a74a0fd0]
2022-06-10 09:36:41.141 WARN 12924 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 23505, SQLState: 23505
2022-06-10 09:36:41.142 ERROR 12924 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : Unique index or primary key violation: "PUBLIC.PRIMARY_KEY_8 ON PUBLIC.CONTAINER(ID) VALUES ( /* 1 */ CAST(X'b8718f198a5c480abcb4a116a74a0fd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' AS BINARY(255)) )"; SQL statement:
/* insert org.testing.spring.data.jpa [23505-212]
2022-06-10 09:36:41.142 INFO 12924 --- [ main] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["PUBLIC.PRIMARY_KEY_8 ON PUBLIC.CONTAINER(ID) VALUES ( /* 1 */ CAST(X'b8718f198a5c480abcb4a116a74a0fd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' AS BINARY(255)) )"; SQL statement:
/* insert org.testing.spring.data.jpa [23505-212]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:276)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
at jdk.proxy2/jdk.proxy2.$Proxy111.save(Unknown Source)
at org.testing.spring.data.jpa.repository.ContainerRepositoryTests.testSaveContainer(ContainerRepositoryTests.java:39)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:577)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:59)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:37)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:99)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:200)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:46)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3375)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3908)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:107)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478)
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:344)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1407)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:489)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3290)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2425)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:449)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562)
... 82 more
Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PUBLIC.PRIMARY_KEY_8 ON PUBLIC.CONTAINER(ID) VALUES ( /* 1 */ CAST(X'b8718f198a5c480abcb4a116a74a0fd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' AS BINARY(255)) )"; SQL statement:
/* insert org.testing.spring.data.jpa [23505-212]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:508)
at org.h2.message.DbException.getJdbcSQLException(DbException.java:477)
at org.h2.message.DbException.get(DbException.java:223)
at org.h2.message.DbException.get(DbException.java:199)
at org.h2.index.Index.getDuplicateKeyException(Index.java:525)
at org.h2.mvstore.db.MVSecondaryIndex.checkUnique(MVSecondaryIndex.java:223)
at org.h2.mvstore.db.MVSecondaryIndex.add(MVSecondaryIndex.java:184)
at org.h2.mvstore.db.MVTable.addRow(MVTable.java:519)
at org.h2.command.dml.Insert.insertRows(Insert.java:174)
at org.h2.command.dml.Insert.update(Insert.java:135)
at org.h2.command.dml.DataChangeStatement.update(DataChangeStatement.java:74)
at org.h2.command.CommandContainer.update(CommandContainer.java:174)
at org.h2.command.Command.executeUpdate(Command.java:252)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:209)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:169)
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:197)
... 103 more
CodePudding user response:
Hibernate already does select by id before saving detached entity. But the problem is that hibernate can't find entity by uuid. I don't know exactly how it works (it is possible that the problem is in the DBMS), but you can fix it by adding @Type annotation:
@Entity
public class Container {
@Id
@Type(type = "uuid-char")
private UUID id;
}
CodePudding user response:
Spring Data JPA should already detect, that the entity is not new and should call merge.
You could make your entity implement Persistable which should fix the problem.
Alternatively, you could create a breakpoint in SimpleJpaRepository.save(..) and debug, why Spring Data JPA doesn't consider your entity new.
