我有这些表格:
CREATE TABLE PRODUCT (
ID NUMBER(19,0) NOT NULL,
CONSTRAINT PRODUCT_PK
PRIMARY KEY (ID)
USING INDEX (
CREATE UNIQUE INDEX PRODUCT_PK
ON PRODUCT(ID)
...
)
)
...
CREATE TABLE PRODUCT_LOCALE (
PRODUCT_ID NUMBER(19,0) NOT NULL,
LOCALE VARCHAR2(12 CHAR) NOT NULL,
NAME VARCHAR2(160 CHAR),
CONSTRAINT PRODUCT_LOCALE_PK
PRIMARY KEY (PRODUCT_ID,LOCALE)
)
...
由本课程代表:
public class Product extends LocalizedEntity<Product.LocalizedFields> {
....
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public static class LocalizedFields implements Serializable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
及其超级
public abstract class LocalizedEntity<T> implements serializable {
....
private Map<Locale, T> localizedFields = new HashMap<Locale, LF>();
public Map<Locale, T> getLocalizedFields() {
return localizedFields;
}
public void setLocalizedFields(Map<Locale, T> localizedFields) {
this.localizedFields = localizedFields;
}
}
我正在使用Hibernate和.hbm.xml文件,这个标签正在运行:
.....
<map name="localizedFields" table="product_locale" lazy="false" fetch="select" batch-size="100">
<cache usage="read-write" />
<key column="product_id" not-null="true" />
<map-key type="locale">
<column name="locale" length="12" not-null="true" />
</map-key>
<composite-element class="com.myproject.Product$LocalizedFields">
<property name="name" type="string">
<column name="name" length="500" />
</property>
</composite-element>
</map>
.....
现在我必须使用Annotations,所以我已经迁移到了这个:
@Entity
@Table(name = "product")
public class Product extends LocalizedEntity<Product.LocalizedFields> {
....
private Long id;
@Id
@Column(name = "id")
@GeneratedValue(strategy= GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@ElementCollection(fetch = FetchType.EAGER)
@JoinTable(name = "product_locale", joinColumns = @JoinColumn(name = "product_id", nullable = false))
@MapKeyClass(value = Locale.class)
@MapKeyColumn(name = "locale", length = 12, nullable = false)
@BatchSize(size = 100)
@Fetch(FetchMode.SELECT)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Embedded
public Map<Locale, LocalizedFields> getLocalizedFields() {
return super.getLocalizedFields();
}
@Embeddable
public static class LocalizedFields implements Serializable {
....
private String name;
@Column(name = "name", length = 500, nullable = false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
而且......
@MappedSuperclass
public abstract class LocalizedEntity<T> implements serializable {
....
private Map<Locale, T> localizedFields = new HashMap<Locale, LF>();
public Map<Locale, T> getLocalizedFields() {
return localizedFields;
}
public void setLocalizedFields(Map<Locale, T> localizedFields) {
this.localizedFields = localizedFields;
}
}
它抛出了这个错误:
引起:org.hibernate.MappingException:无法确定:java.util.Map的类型,在表:product,对于列:[org.hibernate.mapping.Column(localizedFields)] 在org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:349) 在org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:322) 在org.hibernate.mapping.Property.isValid(Property.java:241) 在org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:496) 在org.hibernate.mapping.RootClass.validate(RootClass.java:270) 在org.hibernate.cfg.Configuration.validate(Configuration.java:1360) 在org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1851) 在org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930) 在org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372) 在org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:454) 在org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439) 在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633) 在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570) ... 103更多
如果我用@MapKey替换@MapKeyClass(value = Locale.class)和@MapKeyColumn(&#34; locale&#34;)会抛出此错误:
引起:org.hibernate.AnnotationException:找不到关联的类:com.myproject.Product $ LocalizedFields at org.hibernate.cfg.annotations.MapBinder.bindKeyFromAssociationTable(MapBinder.java:133) at org.hibernate.cfg.annotations.MapBinder.access $ 000(MapBinder.java:76) 在org.hibernate.cfg.annotations.MapBinder $ 1.secondPass(MapBinder.java:111) 在org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70) 在org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1697) 在org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1426) 在org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846) 在org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930) 在org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372) 在org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:454) 在org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439) 在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633) 在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570) ... 103更多
答案 0 :(得分:0)
我发现问题是关键&#34; Locale&#34;
根据JPA文档(http://docs.oracle.com/javaee/6/api/index.html?javax/persistence/MapKeyClass.html):
&#34;指定类型关联的映射键的类型 java.util.Map。 map键可以是基本类型,可嵌入类, 或实体&#34;
Locale不是基本类型,可嵌入或实体,它是Hibernate使用其内部类型&#34; locale&#34;管理的自定义类型。 (它是org.hibernate.type.LocaleType的别名),因此JPA没有注释来管理它。
要解决它,我们必须使用Hibernate添加的注释@MapKeyType来映射UserTypes或Hibernate的自定义类型,而不是注释JPA(https://hibernate.atlassian.net/browse/HHH-5507)。
通过这些注释,它必须起作用:
@ElementCollection(fetch = FetchType.EAGER)
@JoinTable(name = "product_locale", joinColumns = @JoinColumn(name = "product_id", nullable = false))
@MapKeyColumn(name = "locale", length = 12, nullable = false)
@MapKeyType(value = @Type(type = "locale"))
@BatchSize(size = 100)
@Fetch(FetchMode.SELECT)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
答案 1 :(得分:0)
注释 @MappedSuperclass 文档:
指定一个其映射信息应用于的类 从中继承的实体。映射的超类没有单独的 为它定义的表。
当hibernate构建映射时,它为每个类创建一个 org.hibernate.mapping.PersistentClass ,并且对于每个属性一个'value',根据注释(org。)有不同类型的值。 hibernate.mapping.ManyToMany,org.hibernate.mapping.OneToMany,org.hibernate.mapping.SimpleValue等)。注释 @ElementCollection 必须声明为 org.hibernate.mapping.Component 但如果您看到堆栈跟踪错误来自SimpleValue:
引起:org.hibernate.MappingException:无法确定:java.util.Map的类型,在表:product,对于列:[org.hibernate.mapping.Column(localizedFields)]在 org。 hibernate.mapping.SimpleValue .getType(SimpleValue.java:349)at ....
Hibernate忽略了在子元素上声明的注释,简单的解决方案是删除注释 @MappedSuperclass 。
另一个解决方案是告诉孩子们hibernate该字段已被覆盖,但我尝试使用 @AssociationOverride 或 @AttributeOverride 但没有成功。< / p>