2017年4月21日 星期五

自定義Hibernate Type

原始問題:
某個老舊的table設定,其中一個欄位設char(10)
結果裡面的值有長有短,不足10碼的就自動補空白
導致在後端處理的時候處理很麻煩

當然最簡單的方式是改DB欄位設定
但總不是如人所願
所以只好針對Hibernate轉Bean的時候下手

先談失敗的改法:
我修改Hibernate塞Bean的時候一定要透過set方法 (找不到怎麼設的了QQ)
然後我在set方法中寫trim的動作
承原始問題,那些char設定很多都用在Primary Key
最後用Bean Update資料的時候就爆炸了
Exception在Hibernate這邊,還沒到DB
Exception的大意是Bean的Id被改過 (很久以前,也懶得還原當時情況了)

後來就改為現在這邊要介紹的方法

先自定義Hibernate Type
public class CustomerTrimStringType implements UserType{

    private int sqlType(){
        return Types.VARCHAR;
    }

    @Override
    public Object assemble(Serializable arg0, Object arg1) throws HibernateException {
        return null;
    }

    @Override
    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    @Override
    public Serializable disassemble(Object arg0) throws HibernateException {
        return null;
    }

    @Override
    public boolean equals(Object value1, Object value2) throws HibernateException {
        if (value1 == null) {
            if (value2 != null) {
                return false;
            }
            return true;
        }

        return value1.equals(value2);
    }

    @Override
    public int hashCode(Object value) throws HibernateException {
        return value == null ? 0 : value.hashCode();
    }

    @Override
    public boolean isMutable() {
        return false;
    }

    @Override
    public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
        throws HibernateException, SQLException
    {
        Object value = rs.getString(names[0]);
        if ((value == null) || (rs.wasNull())){
            return null;
        }

        return value.toString().trim();
    }

    @Override
    public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor arg3)
        throws HibernateException, SQLException
    {
        if(value == null){
            st.setNull(index, sqlType());
        }else{
            st.setString(index, (String)value);
        }
    }

    @Override
    public Object replace(Object arg0, Object arg1, Object arg2) throws HibernateException {
        return null;
    }

    @Override
    public Class returnedClass() {
        return String.class;
    }

    @Override
    public int[] sqlTypes() {
        return new int[]{ Types.VARCHAR };
    }
}

在45行nullSafeGet這個方法做修改
另外,沒意外的話nullSafeSet這個方法是Hibernate -> DB的動作

設定Hibernate Bean的欄位要使用自定義的Type
public class TableBean {

    private String column1;

    @Column(name = "column1")
    @Type(type="packageName.CustomerTrimStringType")
    public String getColumn1() {
        return this.Column1;
    }

    public void setColumn1(String column1){
        this.column1 = column1;
    }
}

沒有留言:

張貼留言