2

I get the following error when validating a set of JPA-entities against a database-schema with 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

The underlying database is PostgreSQL 9.1 and the relevant database-tables are defined thus:

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
);

The entities are defined as follows:

@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;
    }
}

Finally, the class defining the primary key for 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;
    }
}

Why is Hibernate expecting a bytea in the column country? And how can I convince the validator to accept the schema as is?

1 Answer 1

1

To answer my own question: Hibernate was treating the dependency not as an entity, but as an object to be serialised and stored as such in the database. The solution was to change the data-type of the field "country" in PostalCodePK to String and to switch to using an embedded ID while adding the annotation @MapsId to the field "country" in PostalCode:

    @EmbeddedId
    PostalCodePK id;

    @MapsId("country")
    @ManyToOne
    @JoinColumn(name="country")
    private Country country;
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.