簡體   English   中英

以語言環境為鍵的地圖的休眠注釋

[英]Hibernate Annotation for Map with Locale as Key

我有這些表:

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>
.....

現在,我必須使用注釋,因此我已遷移至此:

@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。 org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:322)的org.hibernate.mapping.Property.isValid(Property.java:241)的getType(SimpleValue.java:349)org.hibernate.mapping.PersistentClass的getType(SimpleValue.java:322) org.hibernate.mapping.RootClass.validate(RootClass.java:270)的org.hibernate.cfg.Configuration.validate(Configuration.java:1360)的org.hibernate.cfg的.validate(PersistentClass.java:496)。 org.hibernate.cfg處的Configuration.buildSessionFactory(Configuration.java:1851)org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372)處的org.springframework.orm.hibernate4.LocalSessionFactoryBuilder(Configuration.java:1930) org.springframework.orm.hib上的.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:454) org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633)的ernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439)在org.springframework.beans.factory.support.AbstractAutowireCapableBeanBean(Factory java:1570)...還有103

如果我將@MapKeyClass(value = Locale.class)和@MapKeyColumn替換為@MapKey(“ locale”),則會引發此錯誤:

引起原因:org.hibernate.AnnotationException:找不到關聯的類:org.hibernate.cfg.annotations.MapBinder.bindKeyFromAssociationTable(MapBinder.java:133)處的com.myproject.Product $ LocalizedFields org.hibernate.cfg.annotations.MapBinder處org.hibernate.cfg.annotations處的.access $ 000(MapBinder.java:76).org處的org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:70)處的MapBinder $ 1.secondPass(MapBinder.java:111)。 org上的org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1426)的org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)的hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1697) org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java.org上的.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930) :454)a 在org.springframework.beans.factory.support上的org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439)在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1633) .AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1570)... 103更多

我發現問題出在“語言環境”鍵上

根據JPA文檔( http://docs.oracle.com/javaee/6/api/index.html?javax/persistence/MapKeyClass.html ):

“為類型java.util.Map的關聯指定映射鍵的類型。映射鍵可以是基本類型,可嵌入類或實體”

語言環境不是基本類型,可嵌入的或實體,它是Hibernate使用其內部類型“語言環境”管理的自定義類型(它是org.hibernate.type.LocaleType的別名),因此JPA沒有注釋來管理此類型。

要解決它,我們必須使用Hibernate添加的注釋@MapKeyType來映射用戶類型或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)

注釋@MappedSuperclass文檔:

指定一個類,將其映射信息應用於從其繼承的實體。 映射的超類沒有為其定義單獨的表。

當hibernate構建映射時,它將為每個類創建一個org.hibernate.mapping.PersistentClass ,並且為每個屬性創建一個“值”,根據注釋的不同,值的類型也不同(org.hibernate.mapping.ManyToMany,org.hibernate。 mapping.OneToMany,org.hibernate.mapping.SimpleValue等)。 注解@ElementCollection必須聲明為org.hibernate.mapping.Component,但是如果您看到stacktrace,則錯誤來自SimpleValue:

由以下原因引起:org.hibernate.MappingException:無法確定類型:java.util.Map,在表:product,對於列:[org.hibernate.mapping.Column(localizedFields)]在org.hibernate.mapping.SimpleValue 。 getType(SimpleValue.java:349)在...

Hibernate忽略了在子級上聲明的注釋,簡單的解決方案是刪除@MappedSuperclass注釋。

另一個解決方案是告訴孩子休眠狀態,該字段已被覆蓋,但是我嘗試使用@AssociationOverride@AttributeOverride失敗。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM