以区域设置为键的地图的Hibernate注释

时间:2015-06-15 21:06:42

标签: java hibernate annotations

我有这些表格:

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更多

2 个答案:

答案 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>