用typehandler优雅的解决枚举类型的读写

问题

  1. 当数据库表字段是枚举类型的码值的时候,往往要根据字段注释找对应的业务值。随着业务的发展,产生了新的码值,而数据库表的注释往往不会跟着变。新的码值的业务含义就很难知道了。
  2. 对应的DO类的字段亦是如此。有了新的码值,字段的注释一般跟不上。

解决办法

表字段是码值的时候,一般会有一个枚举(enum)类对应。我们可以把DO类的对应字段定义为枚举类型,用mybatis的typehandler来处理读写。
这样做之后,就只需要维护枚举类型,数据库字段和DO类的注释都不需要了。最好的注释就是对应的枚举类
通过枚举类强管控码值的变化,就不会随着时间的推移,代码的可读性和可维护性大大降低了。

具体做法

1 枚举字段类型定义, 我们的目标是直接把这个类型入库,并正确的读取出来。

public enum TerminalEnum {
    
    
	
	HTTP("http", "http接口"),
	DUBBO("dubbo", "dubbo接口"),
	WEB("web", "网页"),
	;
	
	TerminalEnum(String t, String n) {
    
    
		this.type = t;
		this.name = n;
	}
	
	@Override
	public String toString() {
    
    
		return this.name;
	}
	
	@Getter
	private String type;
	@Getter
	private String name;
	
	public static TerminalEnum getEnumByType(String type) {
    
    
		TerminalEnum[] values = TerminalEnum.values();
		for (TerminalEnum terminalEnum : values) {
    
    
			if (StringUtils.equalsIgnoreCase(type, terminalEnum.type)) {
    
    
				return terminalEnum;
			}
		}
		return null;
	}
}

2 typehandler定义, 需要继承 org.apache.ibatis.type.BaseTypeHandler

读写的逻辑

  1. 写的时候取枚举的type字段
  2. 读的时候根据type字段转成枚举类型
public class TerminalEnumHandler extends BaseTypeHandler<TerminalEnum> {
    
    
	
	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, TerminalEnum terminalEnum, JdbcType jdbcType) throws SQLException {
    
    
		if (terminalEnum == null) {
    
    
			return;
		}
		
		// 入库的时候取枚举的type字段
		ps.setString(i, terminalEnum.getType());
	}
	
	@Override
	public TerminalEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
    
    
		String type = rs.getString(columnName);
		if (StringUtils.isBlank(type)) {
    
    
			return null;
		} else {
    
    
			// 读的时候根据type字段转成枚举类型
			return TerminalEnum.getEnumByType(type);
		}
	}
	
	@Override
	public TerminalEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    
    
		String type = rs.getString(columnIndex);
		if (StringUtils.isBlank(type)) {
    
    
			return null;
		} else {
    
    
			return TerminalEnum.getEnumByType(type);
		}
	}
	
	@Override
	public TerminalEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    
    
		String type = cs.getString(columnIndex);
		if (StringUtils.isBlank(type)) {
    
    
			return null;
		} else {
    
    
			return TerminalEnum.getEnumByType(type);
		}
	}
}

3 我的应用不需要手动注册这个typehandler
4 resultMap对应的字段加上typehandler

<resultMap id="BaseResultMap" type="com.***.***DO" >
... ... 
	<result column="terminal" property="terminal"  typeHandler="com.***.typehandler.TerminalEnumHandler"/>
</resultMap>

5 insert或者update的时候需要在字段后面带上typehandler

	<update id="updateTerminal" >
		UPDATE  ***_token
		SET
		terminal=#{terminal, typeHandler=com.***.typehandler.TerminalEnumHandler}
		WHERE id=#{id}
	</update>

猜你喜欢

转载自blog.csdn.net/bruce128/article/details/126428607