데이터베이스 스키마에서 테이블의 column을 CHAR 타입으로 정의한 경우에 이 값을 java string 으로 읽어들이면 SessionFactory 인스턴스를 만드는 과정에서 아래와 같은 예외가 발생한다.

org.hibernate.HibernateException: Wrong column type ...


org.hibernate.HibernateException: Wrong column type in lodgingdb.participants for column pctSSN1. Found: char, expected: varchar(6)
    at org.hibernate.mapping.Table.validateColumns(Table.java:284)
    at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1174)
    at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:139)
    at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:387)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1385)
    ....

(예외를 보려면 hibernate config xml 에서 hibernate.hbm2ddl.auto 값을 validate 로 지정해주어야 한다. validate는 테이블과 이에 대응하는 클래스 간의 타입 일치 여부를 검사하고 맞지 않으면 위처럼 예외를 던진다. 이 값을 "update"로 지정하면 hibernate가 DB 스키마를 변경해서 예외가 발생하지 않게 한다. 자세한 내용은 gyumee.egloos.com 을 참고하시길..)

자바 클래스 Participant 의 property인 ssn1 은  아래와 같이 String 타입으로 되어있고....
대응하는 Table DDL 은 아래와 같다.
그리고 이에 대한 hibernate config 파일인 Participant.hbm.xml

위의 예외 메세지를 해석하면

Participant.hbm.xml 을 봤을때에는 컬럼 pctSSN1의 데이터 타입이 길이가 6인 varchar, 즉 varchar(6) 일줄 알았는데, DB 스키마를 보니 char 형이어서 양쪽의 타입이 일치하지 않는다.

는 뜻으로 풀이됨.

디버그를 돌려보면 Table.validateColumns 메소드에서 문제가 발생함.

Table.validateColumns


Participant.hbm.xml 을 해석한 후 등록된 ColumnMetadata의 instance 내용을 보면 아래와 같이 나오는데, pctSSN1 column의 type 이 CHAR 라고 나온다. (ColumnMetadata는 데이터베이스의 스키마를 읽어서 얻어낸 metadata를 나타낸다.)

그런데 위에서 class 프로퍼티인 ssn1( 테이블 Participant의 pctSSN1에 대응한다)의 타입을 "string" 이라고 명시했으니 타입 불일치 발생.

구체적으로 살펴보면, Participant.hbm.xml 에서 ssn1 프로퍼티의 타입을 "string"으로 지정해줌으로써(지정해주지 않더라도 reflection으로 ssn1의 타입인 java.lang.String을 알아낸다.) 아래와 같이 StringType 으로 저장이 된다.

그리고 StringType의 실제 대응하는 SQL Type은 아래에서 보듯이 VARCHAR로 되어있다.

domain layer 와 db layer 간의 property-column 의 타입을 맞춰보는데, 한쪽은 VHARCHAR 이고 다른 한 쪽은 CHAR 로 나오니 결국 검증이 실패하게 된 것..


해결방법은 하이버네이트 문서 5.1.22 Column and formula elements 를 참고해서 <property ...> </property> element 안에 다음과 같이 <column /> 을 정의해주고 sql-type="char" 로 지정해주면 타입 불일치 문제가 해결된다.

show >>

어노테이션 annotation 방식에서는 이쪽 블로그에서 나오듯이 프로퍼티에 columnDefinition="char" 로 지정하면 된다고 나온다.

    // ref : Cedar715's Blog
    @Column(name = “CNTRY_NM”, columnDefinition = “char”)
    public String getCountry() {
        return country;
    }


써놓고 나서 하이버네이트 문서를 보니 basic type에 대해서 다음과 같이 쓰여있다.

5.2.2 Basic value types

string
    A type mapping from java.lang.String to VARCHAR (or Oracle VARCHAR2).

아... 역시 문서를 잘 봐야 함.. -_-;;
Posted by yeori
,