自动封装字典类型字段的一种小策略

字典数据在数据库中一般只存value属性,个别表为提高查询效率,会做适当的冗余处理。把字典名称冗余到表中。其他情况下,都要求把value和name同时返回给前端。过去,项目的做法通常需要在返回对象里另定义名称字段,然后调用工具类设置名称,如下图:

		this.nationName = findDictName(DictType.nation_type, commonMember.getNation());
		this.deleName = findDictName(DictType.dele_type, commonMember.getDeleId());
		this.partyName = findDictName(DictType.party_type, commonMember.getParty());
		this.committeeName = findDictName(DictType.committee_type, commonMember.getCommittee());

该类形式代码遍及整个项目,对于一个程序员来说,观感极度不舒服。-.-,因此,在重构的项目中采取一字典类型处理机制这种小技巧。

字典类型:

public class DictColumn {

    private String value;

    private String name;

    private String dictCode;
}

mybatis类型处理器:

// 对原生的类型处理包装下
@MappedJdbcTypes({JdbcType.VARCHAR})
public abstract class MyTypeHandler<T> extends BaseTypeHandler<T> {

    public abstract String getSetValue(T t);


    public abstract T buildResultModel(String value, String columnName);

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType)
            throws SQLException {
        String setValue = getSetValue(parameter);
        if (null != parameter && ZYStrUtils.isNotNull(setValue)) {
            ps.setString(i, setValue);
        } else {
            ps.setString(i, null);
        }
    }


    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return buildResultModel(rs.getString(columnName), columnName);
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String columnName = Optional.ofNullable(rs.getMetaData()).map(md -> getColumnName(columnIndex, md)).orElse(null);
        return buildResultModel(rs.getString(columnIndex), columnName);
    }


    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String columnName = Optional.ofNullable(cs.getMetaData()).map(md -> getColumnName(columnIndex, md)).orElse(null);
        return buildResultModel(cs.getString(columnIndex), columnName);
    }


    private String getColumnName(int columnIndex, ResultSetMetaData md) {
        try {
            return md.getColumnName(columnIndex);
        } catch (SQLException e) {
            return null;
        }
    }
}

@Component
public class DictTypeHandler extends MyTypeHandler<DictColumn> {

    @Override
    public String getSetValue(DictColumn dictColumn) {
        return null != dictColumn ? dictColumn.getValue() : null;
    }

    @Override
    public DictColumn buildResultModel(String dictValue, String columnName) {
        DictColumn dictColumn = new DictColumn();
        if (ZYStrUtils.isNull(columnName)) {
            return dictColumn;
        }
        // 此处需要注意下:字典类型code用的是数据库的小写字段名。建表时,不同表使用相同的字
        // 典要建相同的字段名才能自动封装。之所以这么弄是因为在类型处理器中,是没办法通过反射
        // 的方式获取到实体类字段的注解信息的。没法通过一些注解来标识字典类型
        String dictCode = columnName.toLowerCase();
        dictColumn.setDictCode(dictCode);
        dictColumn.setValue(dictValue);
        dictColumn.setLabel(ZYDictHelper.dictName(dictCode, dictValue));
        return dictColumn;
    }
}

实体类中效果:

    @Column(varcharColumn = true, varcharLength = 60, value = "性别")
    @TableField("sex")
    private DictColumn sex;

    @Column(varcharColumn = true, varcharLength = 100, value = "出生地")
    @TableField("birth_place")
    private String birthPlace;

    @Column(varcharColumn = true, varcharLength = 60, value = "民族")
    @TableField("nation")
    private DictColumn nation;

返回数据效果:
自动封装字典类型字段的一种小策略_第1张图片

你可能感兴趣的:(java)