2013-08-01 64 views
1

我得到驗證一組JPA-實體時針對數據庫型模式與Hibernate以下錯誤:休眠架構驗證上固定長度的字符字段失敗

Caused by: org.hibernate.HibernateException: Wrong column type in public.postal_code for column country. Found: bpchar, expected: bytea 
    at org.hibernate.mapping.Table.validateColumns(Table.java:282) 
    at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1268) 
    at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:155) 
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:460) 
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1737) 
    at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:84) 
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904) 
    ... 9 more 

底層數據庫是PostgreSQL的9.1和相關數據庫表這樣定義:

CREATE TABLE country 
(
    code_alpha2 character(2) NOT NULL, -- ISO 3166 alpha2 code 
    code_alpha3 character(3), -- ISO 3166 alpha3 code 
    CONSTRAINT country_pkey PRIMARY KEY (code_alpha2) 
) 
WITH (
    OIDS=FALSE 
); 

CREATE TABLE postal_code 
(
    country character(2) NOT NULL, -- ISO 3166 alpha2 country-code 
    code character varying(12) NOT NULL, -- Postal code proper 
    CONSTRAINT postal_code_pk PRIMARY KEY (country, code), 
    CONSTRAINT country_fk FOREIGN KEY (country) 
     REFERENCES country (code_alpha2) MATCH SIMPLE 
     ON UPDATE NO ACTION ON DELETE NO ACTION 
) 
WITH (
    OIDS=FALSE 
); 

這些實體定義如下:

@Entity 
public class Country implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @Column(name="code_alpha2", columnDefinition="bpchar") 
    private String codeAlpha2; 

    @Column(name="code_alpha3", columnDefinition="bpchar") 
    private String codeAlpha3; 

    public Country() { 
    } 

    public String getCodeAlpha2() { 
     return this.codeAlpha2; 
    } 

    public void setCodeAlpha2(String codeAlpha2) { 
     this.codeAlpha2 = codeAlpha2; 
    } 

    public String getCodeAlpha3() { 
     return this.codeAlpha3; 
    } 

    public void setCodeAlpha3(String codeAlpha3) { 
     this.codeAlpha3 = codeAlpha3; 
    } 
} 

@Entity 
@IdClass(PostalCodePK.class) 
@Table(name="postal_code") 
public class PostalCode implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @ManyToOne(fetch=FetchType.EAGER) 
    @JoinColumn(name="country") 
    private Country country; 

    @Id 
    private String code; 

    public PostalCode() { 
    } 

    public Country getCountry() { 
     return country; 
    } 

    public void setCountry(Country country) { 
     this.country = country; 
    } 

    public String getCode() { 
     return code; 
    } 

    public void setCode(String code) { 
     this.code = code; 
    } 
} 

最後,類定義POSTAL_CODE主鍵:

@Embeddable 
public class PostalCodePK implements Serializable { 
    //default serial version id, required for serializable classes. 
    private static final long serialVersionUID = 1L; 

    @Column(columnDefinition="bpchar") 
    private Country country; 

    private String code; 

    public PostalCodePK() { 
    } 
    public Country getCountry() 
     return this.country; 
    } 
    public void setCountry(Country country) { 
     this.country = country; 
    } 
    public String getCode() { 
     return this.code; 
    } 
    public void setCode(String code) { 
     this.code = code; 
    } 
    public boolean equals(Object other) { 
     if (this == other) { 
      return true; 
     } 
     if (!(other instanceof PostalCodePK)) { 
      return false; 
     } 
     PostalCodePK castOther = (PostalCodePK)other; 
     return 
      this.country.equals(castOther.country) 
      && this.code.equals(castOther.code); 
    } 

    public int hashCode() { 
     final int prime = 31; 
     int hash = 17; 
     hash = hash * prime + this.country.hashCode(); 
     hash = hash * prime + this.code.hashCode(); 

     return hash; 
    } 
} 

爲什麼休眠預計在列全國BYTEA?我該如何說服驗證者接受模式?

回答

1

爲了回答我自己的問題:Hibernate將依賴不是作爲一個實體,而是作爲一個對象被序列化並存儲在數據庫中。解決方案是將PostalCodePK中字段「country」的數據類型更改爲String,並切換爲使用嵌入ID,同時將註釋@MapsId添加到PostalCode中的「country」字段中:

@EmbeddedId 
    PostalCodePK id; 

    @MapsId("country") 
    @ManyToOne 
    @JoinColumn(name="country") 
    private Country country;