我尝试在hibernate 4.3.1.Final的实体中保留@ElementCollection
。该实体看起来像这样:
import javax.persistence.*;
import java.util.Map;
@Entity
public class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@ElementCollection
private Map<CompositeKey, CompositeValue> map;
@Embeddable
public static class CompositeKey {
@Basic
private Integer key1;
@Basic
private Integer key2;
}
@Embeddable
public static class CompositeValue {
@Basic
private Integer val1;
@Basic
private Integer val2;
}
}
Hibernate正确生成架构:
create table MyEntity (id integer not null, primary key (id)) ENGINE=InnoDB;
create table MyEntity_map (MyEntity_id integer not null, val1 integer, val2 integer, key1 integer, key2 integer, primary key (MyEntity_id, key1, key2)) ENGINE=InnoDB;
create table ReferencedEntity (id integer not null, primary key (id)) ENGINE=InnoDB;
alter table MyEntity_map add constraint FK_mhu8q8dtieguddm0w4gxfwhnc foreign key (MyEntity_id) references MyEntity (id);
但是当我将CompositeKey
更改为引用另一个Entity
时,当hibernate在启动时生成元模型时,我得到QueryException
。
更改后的代码:
@Embeddable
public static class CompositeKey {
@ManyToOne
private ReferencedEntity key1;
@Basic
private Integer key2;
}
引用的Entity
:
import javax.persistence.*;
@Entity
public class ReferencedEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
}
例外:
Caused by: org.hibernate.QueryException: could not resolve property: key1 of: component[val1,val2]
at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:83) ~[AbstractPropertyMapping.class:4.3.1.Final]
at org.hibernate.persister.entity.AbstractPropertyMapping.toColumns(AbstractPropertyMapping.java:98) ~[AbstractPropertyMapping.class:4.3.1.Final]
at org.hibernate.persister.collection.AbstractCollectionPersister.toColumns(AbstractCollectionPersister.java:1625) ~[AbstractCollectionPersister.class:4.3.1.Final]
at org.hibernate.loader.plan.build.internal.spaces.CompositePropertyMapping.toColumns(CompositePropertyMapping.java:124) ~[CompositePropertyMapping.class:4.3.1.Final]
at org.hibernate.loader.plan.build.internal.spaces.CompositeQuerySpaceImpl.toAliasedColumns(CompositeQuerySpaceImpl.java:52) ~[CompositeQuerySpaceImpl.class:4.3.1.Final]
at org.hibernate.loader.plan.build.internal.spaces.JoinImpl.resolveAliasedLeftHandSideJoinConditionColumns(JoinImpl.java:79) ~[JoinImpl.class:4.3.1.Final]
at org.hibernate.loader.plan.exec.internal.LoadQueryJoinAndFetchProcessor.addJoins(LoadQueryJoinAndFetchProcessor.java:261) ~[LoadQueryJoinAndFetchProcessor.class:4.3.1.Final]
at org.hibernate.loader.plan.exec.internal.LoadQueryJoinAndFetchProcessor.renderEntityJoin(LoadQueryJoinAndFetchProcessor.java:193) ~[LoadQueryJoinAndFetchProcessor.class:4.3.1.Final]
at org.hibernate.loader.plan.exec.internal.LoadQueryJoinAndFetchProcessor.renderJoin(LoadQueryJoinAndFetchProcessor.java:158) ~[LoadQueryJoinAndFetchProcessor.class:4.3.1.Final]
at org.hibernate.loader.plan.exec.internal.LoadQueryJoinAndFetchProcessor.processQuerySpaceJoin(LoadQueryJoinAndFetchProcessor.java:137) ~[LoadQueryJoinAndFetchProcessor.class:4.3.1.Final]
at org.hibernate.loader.plan.exec.internal.LoadQueryJoinAndFetchProcessor.processQuerySpaceJoins(LoadQueryJoinAndFetchProcessor.java:132) ~[LoadQueryJoinAndFetchProcessor.class:4.3.1.Final]
at org.hibernate.loader.plan.exec.internal.LoadQueryJoinAndFetchProcessor.processQuerySpaceJoin(LoadQueryJoinAndFetchProcessor.java:138) ~[LoadQueryJoinAndFetchProcessor.class:4.3.1.Final]
at org.hibernate.loader.plan.exec.internal.LoadQueryJoinAndFetchProcessor.processQuerySpaceJoins(LoadQueryJoinAndFetchProcessor.java:132) ~[LoadQueryJoinAndFetchProcessor.class:4.3.1.Final]
at org.hibernate.loader.plan.exec.internal.LoadQueryJoinAndFetchProcessor.processQuerySpaceJoins(LoadQueryJoinAndFetchProcessor.java:113) ~[LoadQueryJoinAndFetchProcessor.class:4.3.1.Final]
at org.hibernate.loader.plan.exec.internal.AbstractLoadQueryDetails.generate(AbstractLoadQueryDetails.java:171) ~[AbstractLoadQueryDetails.class:4.3.1.Final]
at org.hibernate.loader.plan.exec.internal.BasicCollectionLoadQueryDetails.<init>(BasicCollectionLoadQueryDetails.java:60) ~[BasicCollectionLoadQueryDetails.class:4.3.1.Final]
at org.hibernate.loader.plan.exec.internal.BatchingLoadQueryDetailsFactory.makeCollectionLoadQueryDetails(BatchingLoadQueryDetailsFactory.java:101) ~[BatchingLoadQueryDetailsFactory.class:4.3.1.Final]
at org.hibernate.loader.collection.plan.AbstractLoadPlanBasedCollectionInitializer.<init>(AbstractLoadPlanBasedCollectionInitializer.java:77) ~[AbstractLoadPlanBasedCollectionInitializer.class:4.3.1.Final]
at org.hibernate.loader.collection.plan.CollectionLoader.<init>(CollectionLoader.java:112) ~[CollectionLoader.class:4.3.1.Final]
at org.hibernate.loader.collection.plan.CollectionLoader$Builder.byKey(CollectionLoader.java:105) ~[CollectionLoader$Builder.class:4.3.1.Final]
at org.hibernate.loader.collection.plan.AbstractBatchingCollectionInitializerBuilder.buildNonBatchingLoader(AbstractBatchingCollectionInitializerBuilder.java:45) ~[AbstractBatchingCollectionInitializerBuilder.class:4.3.1.Final]
at org.hibernate.loader.collection.BatchingCollectionInitializerBuilder.createBatchingCollectionInitializer(BatchingCollectionInitializerBuilder.java:71) ~[BatchingCollectionInitializerBuilder.class:4.3.1.Final]
at org.hibernate.persister.collection.BasicCollectionPersister.createCollectionInitializer(BasicCollectionPersister.java:343) ~[BasicCollectionPersister.class:4.3.1.Final]
at org.hibernate.persister.collection.AbstractCollectionPersister.postInstantiate(AbstractCollectionPersister.java:676) ~[AbstractCollectionPersister.class:4.3.1.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:484) ~[SessionFactoryImpl.class:4.3.1.Final]
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1857) ~[Configuration.class:4.3.1.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850) ~[EntityManagerFactoryBuilderImpl$4.class:4.3.1.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843) ~[EntityManagerFactoryBuilderImpl$4.class:4.3.1.Final]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:399) ~[ClassLoaderServiceImpl.class:4.3.1.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842) ~[EntityManagerFactoryBuilderImpl.class:4.3.1.Final]
at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:150) ~[HibernatePersistenceProvider.class:4.3.1.Final]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:336) ~[LocalContainerEntityManagerFactoryBean.class:4.0.1.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318) ~[AbstractEntityManagerFactoryBean.class:4.0.1.RELEASE]
...
我的地图有什么问题?如何防止此异常?
有趣的是,BasicCollectionPersister
似乎已正确初始化。调试显示,例如sqlUpdateRowString
为update MyEntity_map set val1=?, val2=? where MyEntity_id=? and key1_id=? and key2=?
。
答案 0 :(得分:4)
从JPA 2.0规范:
不支持嵌入式id类中定义的关系映射。
另见JPA - EmbeddedId with @ManytoOne。
修改强>
Hibernate 4.3.1.Final实现了JPA 2.1,所以我的第一个猜测错了。 Mea culpa。
映射问题是@ElementCollection
使用嵌入CompositeKey
引用实体ReferencedEntity
。当Hibernate查找AbstractPropertyMapping
(sic!)到CompositeValue
的引用时,抛出ReferencedEntity
中的异常。但是,由于不存在这样的关系,因此抛出异常。对我来说,目前还不清楚这是一个Hibernate错误还是根据JPA 2.1规范。
我看到以下解决方案。
解决方案1
将CompositeKey
更改为Entity
添加id
字段。在这种情况下,可以使用@OneToMany
注释:
@Entity
public class CompositeKey {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@ManyToOne(targetEntity = ReferencedEntity.class)
private ReferencedEntity key1;
@Basic
private Integer key2;
}
解决方案2
添加其他实体CompositeSampler
,其中包含CompositeKey
作为ID,CompositeValue
作为附加属性。 MyEntity
将包含CompositeSampler
的列表。
解决方案3
将CompositeValue
的引用添加到ReferencedEntity
。
顺便说一下,根据JPA 2.1规范:“如果使用嵌入类作为映射键,则嵌入类必须实现hashCode,并且将方法与嵌入映射到的数据库列一致”。