mybatis通用typeHandler(將mysql的json類型轉換爲java對象)

背景:訂單快照信息(收貨地址、商品信息、優惠券信息等)存儲,使用Mysql的json類型字段存放一個java對象的json,但是mybatis不支持json類型,所以通過擴展typeHandler來實現mysql的json字段與java對象的自動轉換,以下爲通用typeHandler源碼,可以用來自動轉換java類型。

直接上源碼:

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.shikuai.domain.json.CommodityJson;
import com.shikuai.domain.json.CouponJson;
import com.shikuai.domain.json.CustomerAddressJson;


/**
 * <b>Description:用以mysql中json格式的字段,進行轉換的自定義轉換器,轉換爲實體類的T類型 屬性</b>
 * <br><b>ClassName:</b> GenericTypeHandler
 * <br><b>Date:</b> 2019年2月17日 下午4:25:07
 * <br>@author <b>jianb.jiang</b>
 */
@MappedTypes(value = {JSONObject.class, CustomerAddressJson.class, CouponJson.class, CommodityJson.class})
@MappedJdbcTypes(value = {JdbcType.VARCHAR}, includeNullJdbcType = true)
public class GenericTypeHandler<T extends Object> extends BaseTypeHandler<T> {

    private Class<T> clazz;
    
    public GenericTypeHandler(Class<T> clazz) {
        if (clazz == null) throw new IllegalArgumentException("Type argument cannot be null");
        this.clazz = clazz;
    }
    
    /**
     * 設置非空參數
     * @param ps
     * @param i
     * @param parameter
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, JSON.toJSONString(parameter));
    }

    /**
     * 根據列名,獲取可以爲空的結果
     * @param rs
     * @param columnName
     * @return
     * @throws SQLException
     */
    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String sqlJson = rs.getString(columnName);
        if (null != sqlJson) {
            return JSONObject.parseObject(sqlJson, clazz);
        }
        return null;
    }

    /**
     * 根據列索引,獲取可以爲空的結果
     * @param rs
     * @param columnIndex
     * @return
     * @throws SQLException
     */
    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String sqlJson = rs.getString(columnIndex);
        if (null != sqlJson) {
            return JSONObject.parseObject(sqlJson, clazz);
        }
        return null;
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String sqlJson = cs.getString(columnIndex);
        if (null != sqlJson) {
            return JSONObject.parseObject(sqlJson, clazz);
        }
        return null;
    }
}

注意:

1、@MappedTypes註解中的類代表此轉換器可以自動轉換爲的java對象,@MappedJdbcTypes註解中設置的是對應的jdbctype,mysql的json對象對應的jdbctype爲VARCHAR。

2、spring boot配置中開啓typeHandler包路徑的自動掃描配置:

mybatis.type-handlers-package=com.shikuai.dao.handler

3、使用上,只需在pojo的屬性中定義需要自動轉換的java對象屬性,如@MappedTypes註解中的CustomerAddressJson,在訂單的pojo中有一個屬性:


    /**
     * 收貨地址快照json
     */
    private CustomerAddressJson reAddressJson;

 

操作和其他pojo的屬性完全一樣,如果像對json對象中的某個屬性進行操作,可以使用mysql支持的json相關函數,具體可以參考這篇文章:https://www.cnblogs.com/ooo0/p/9309277.html

遺留和擴展:如果pojo對象有一個集合屬性呢?這種如何處理?是否可以自定義一個ArrayTypeHandler?pojo中存在集合屬性是否本身就不合理是個僞需求?對於集合屬性的情況,有一篇文章可以參考:https://www.cnblogs.com/kylindai/p/3563818.html

參考文檔:http://www.mybatis.org/mybatis-3/zh/configuration.html#typeHandlers

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章