基于mybatis 类型处理器typeHandlers实现数据库数据到业务对象的转换

在开发中,遇到需要把数据库中存储的json格式的数据转换为java对象中map集合或者list集合你是怎么处理?把数据库中的电话号码,身份证被对称加密的数据解密出来你是怎么处理的?在前后端的时间戳转换为数据库的date日期格式时,你是怎么处理的?

在开发中,主流使用mybatis作为orm框架。从数据库数据库到项目业务对象的数据获取,mybatis提供了typeHandlers插件做转换。在修改语句<insert>,<update><delete>中的使用代码如下:

#{conditions,jdbcType=VARCHAR,typeHandler=com.kuqi.mall.demo.conmon.mybatis.JsonMapHandler}

在select语句的结果集映射的使用,代码如下:

<result property="conditions" column="conditions"  typeHandler="com.kuqi.mall.demo.conmon.mybatis.JsonMapHandler"/>

对于上述的数据,自定义各自的typeHandlers可以快速统一的实现数据转换。插件实现如下分别如下:

JsonMapHandler(json数据转换),JsonListHandler(数组数据转换),AesEncryptorHandler(对称加密,例如电话号码,身份证加密数据转换),AbstractInstantDateHandler(时间戳转换时间)。

JsonMapHandler实现如下:

/**
 * json和map对象的转换
 */
@MappedTypes(Map.class)
public class JsonMapHandler implements TypeHandler<Map<String, Object>> {

    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, Map<String, Object> stringObjectMap, JdbcType jdbcType) throws SQLException {
        preparedStatement.setString(i, CollectionUtils.isEmpty(stringObjectMap) ? null : JSON.toJSONString(stringObjectMap));
    }

    @Override
    public Map<String, Object> getResult(ResultSet resultSet, String s) throws SQLException {
        String jsonStr;
        return StringUtils.isEmpty(jsonStr = resultSet.getString(s)) ? null : JSON.parseObject(jsonStr, Map.class);
    }

    @Override
    public Map<String, Object> getResult(ResultSet resultSet, int i) throws SQLException {
        String jsonStr;
        return StringUtils.isEmpty(jsonStr = resultSet.getString(i)) ? null : JSON.parseObject(jsonStr, Map.class);
    }

    @Override
    public Map<String, Object> getResult(CallableStatement callableStatement, int i) throws SQLException {
        String jsonStr;
        return StringUtils.isEmpty(jsonStr = callableStatement.getString(i)) ? null : JSON.parseObject(jsonStr, Map.class);
    }
}

JsonListHandler实现代码如下:


@MappedTypes(List.class)
public class JsonListHandler implements TypeHandler<List<Object>> {

    @Override
    public void setParameter(PreparedStatement ps, int i, List<Object> parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, CollectionUtils.isEmpty(parameter) ? JSON.toJSONString(parameter) : null);
    }

    @Override
    public List<Object> getResult(ResultSet rs, String columnName) throws SQLException {
        String jsonStr;
        return StringUtils.isNotBlank(jsonStr = rs.getString(columnName)) ? JSON.parseArray(jsonStr, Object.class) : null;
    }

    @Override
    public List<Object> getResult(ResultSet rs, int columnIndex) throws SQLException {
        String jsonStr;
        return StringUtils.isNotBlank(jsonStr = rs.getString(columnIndex)) ? JSON.parseArray(jsonStr, Object.class) : null;
    }

    @Override
    public List<Object> getResult(CallableStatement cs, int columnIndex) throws SQLException {
        String jsonStr;
        return StringUtils.isNotBlank(jsonStr = cs.getString(columnIndex)) ? JSON.parseArray(jsonStr, Object.class) : null;
    }
}
AesEncryptorHandler实现代码如下:

/**
 * Aes 加密
 **/
public class AesEncryptorHandler implements TypeHandler<String> {

    @Override
    public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, StringUtils.isBlank(parameter) ? null : DefaultAbsEncryptor.getInstance().encrypt(parameter));
    }

    @Override
    public String getResult(ResultSet rs, String columnName) throws SQLException {
        String value;
        return StringUtils.isBlank(value = rs.getString(columnName)) ? null : DefaultAbsEncryptor.getInstance().decrypt(value);
    }

    @Override
    public String getResult(ResultSet rs, int columnIndex) throws SQLException {
        String value;
        return StringUtils.isBlank(value = rs.getString(columnIndex)) ? null : DefaultAbsEncryptor.getInstance().decrypt(value);
    }

    @Override
    public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
        String value;
        return StringUtils.isBlank(value = cs.getString(columnIndex)) ? null : DefaultAbsEncryptor.getInstance().decrypt(value);
    }
}
AbstractInstantDateHandler的实现代码如下:

/**
 * @Author iloveoverfly
 * @Date 2020/1/13 9:27
 **/
@Slf4j
public abstract class AbstractInstantDateHandler implements TypeHandler<Object> {

    protected static final Calendar CALENDAR = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));

    @Override
    public void setParameter(PreparedStatement ps, int columnIndex, Object millsObj, JdbcType jdbcType) throws SQLException {

        if (Objects.isNull(millsObj)) {
            return;
        }
        Long mills;
        try {
            if (millsObj instanceof String) {
                mills = Long.parseLong((String) millsObj);
            } else {
                mills = (Long) millsObj;
            }
            doSetParameter(ps, columnIndex, mills, jdbcType);
        } catch (Exception e) {

            log.warn("not match time mills {}", millsObj);
        }
    }

    protected abstract void doSetParameter(PreparedStatement ps, int columnIndex, Long mills, JdbcType jdbcType) throws SQLException;

    @Override
    public Long getResult(ResultSet rs, String columnName) throws SQLException {
        throw new RuntimeSqlException("instant cannot get by getResult(ResultSet rs, String columnName)");
    }

    @Override
    public Long getResult(ResultSet rs, int columnIndex) throws SQLException {
        throw new RuntimeSqlException("instant cannot get by getResult(ResultSet rs, int columnIndex)");
    }

    @Override
    public Long getResult(CallableStatement cs, int columnIndex) throws SQLException {
        throw new RuntimeSqlException("instant cannot get by getResult(CallableStatement cs, int columnIndex)");
    }
}
发布了8 篇原创文章 · 获赞 0 · 访问量 3849

猜你喜欢

转载自blog.csdn.net/new_com/article/details/103925484