首页 > 解决方案 > 如何映射子集使用@ElementCollection

问题描述

我使用 UUID 作为实体的 PK,并且该实体具有Set<UUID>使用@ElementCollection. 持久化父实体时,我得到一个java.lang.ClassCastException: java.lang.String cannot be cast to java.util.UUID

我查看了@MapKeyClass、@Column、@CollectionTable 和@JoinColumn 注释,但没有人提供一种方法来指定子集使用 UUID 表示 FK 及其值。我最后一次尝试是将其添加到属性中@CollectionTable(name = "test_target_files_ids", joinColumns = @JoinColumn(name = "campaign_id", referencedColumnName="id", columnDefinition="binary(16) not null"))

我的实体:

@Entity
public class Campaign
{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    UUID id;
    String name;
    // more attributes...

    @ElementCollection
    Set<UUID> targetFilesIds; // This is just a list of UUIDs representing external files or any other object, it does not matter

我希望实体及其子 UUID 列表被持久化,但只有实体被持久化。我收到此错误消息

java.lang.ClassCastException: java.lang.String cannot be cast to java.util.UUID
    at org.hibernate.type.descriptor.java.UUIDTypeDescriptor.unwrap(UUIDTypeDescriptor.java:20) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.type.descriptor.sql.VarbinaryTypeDescriptor$1.doBind(VarbinaryTypeDescriptor.java:45) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:74) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:276) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:271) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:39) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:912) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1335) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:50) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:478) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:356) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1483) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:512) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3321) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2517) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:178) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:39) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:271) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104) ~[hibernate-core-5.3.12.Final.jar:5.3.12.Final]
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:533) ~[spring-orm-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746) ~[spring-tx-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714) ~[spring-tx-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:534) ~[spring-tx-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:305) ~[spring-tx-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:144) ~[spring-data-jpa-2.1.11.RELEASE.jar:2.1.11.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$ExposeRepositoryInvocationInterceptor.invoke(CrudMethodMetadataPostProcessor.java:364) ~[spring-data-jpa-2.1.11.RELEASE.jar:2.1.11.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.1.11.RELEASE.jar:2.1.11.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.1.10.RELEASE.jar:5.1.10.RELEASE]
    at com.sun.proxy.$Proxy123.save(Unknown Source) ~[na:na]
    at com.mysoftware.service.CampaignService.save(CampaignService.java:83) ~[classes/:na]

(... more lines and no other cause in the stacktrace)

at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.26.jar:9.0.26]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_222]

标签: javaspring-bootjpaspring-data-jpa

解决方案


您应该添加@CollectionTable注释并指定适当的字段名称。类似这样:@CollectionTable(name = "target_files_ids", joinColumns = @JoinColumn(name = "id")) name param in@CollectionTable是将存储信息的表的名称。 name param in@Joincolumn是您的 Campaign 实体上将用于标识target_files_ids表中数据的字段的名称。

看一下这个例子来进一步理解。https://www.callicoder.com/hibernate-spring-boot-jpa-element-collection-demo/

希望能帮助到你。


推荐阅读