Mybatis 的 typeHandler 自定义 枚举类型

版权声明:本文为博主原创文章,如有错误劳烦指正。转载请声明出处,便于读取最新内容。——Bestcxx https://blog.csdn.net/bestcxx/article/details/85016413

前言

在上一篇文章 Mybatis 结合枚举类型 中提到,Mybatis 为枚举类型提供类两种类型控制器,最终体现都效果就是,对于枚举类型要么存储枚举名,要么存储索引值,如果我们想存储别的值怎么办呢?这就是本文要涉及都内容了。

自定义 typeHandler 和 TypeHandler

通过实现 TypeHandler 接口可以实现自定义类型处理器,然后通过一定的配置,就可以使用你喜欢的数据转化效果了。
这个过程的本质是你可以控制数据库插入的数据的最终形态,也可以根据数据库存储数据的形态转化为你期望的形态

自定义 枚举类型的 typeHandler
建议你看一下源码,或者待会你会回来看源码
//EnumTypeHandler
org.apache.ibatis.type.EnumTypeHandler
//EnumOrdinalTypeHandler
org.apache.ibatis.type.EnumOrdinalTypeHandler
看一下对枚举类的常规操作

enum 枚举类型定义常量及调用的应用举例
第三种-重点关注里面包含的静态方法 即可

数据库表结构

有了前面的试探,我们这次简化实验,只用一个字段对应枚举类型

create table ENUM_DEMO
(
	ID bigint not null
		primary key,
	STR2 varchar(32) null,
);
枚举类
public enum Str2Enum {
	
	INIT("init","初始化"),
	ACTIVE("active","激活"),
	FREEZE("freeze","冻结");
	
	private String key;
	private String value;
	public String getKey() {
		return key;
	}
	public String getValue() {
		return value;
	}
	Str2Enum(String key,String value){
		this.key=key;
		this.value=value;
	}
	/**
	 * 根据key值得到对应的枚举类型
	 * @param columnName
	 * @return
	 */
	public static Str2Enum getStr2EnumByKey(String key){
		if("init".equals(key)){
			return INIT;
		}else if("active".equals(key)){
			return ACTIVE;
		}else if("freeze".equals(key)){
			return FREEZE;
		}
		return null;
	}
	
	/**
	 * 根据枚举 value 返回枚举
	 * @param value
	 * @return
	 */
	public static Str2Enum getStr2EnumByValue(String value){
		if("初始化".equals(value)){
			return INIT;
		}else if("激活".equals(value)){
			return ACTIVE;
		}else if("冻结".equals(value)){
			return FREEZE;
		}
		return null;
	}
	
	/**
	 * 根据枚举名字返回类型
	 * @param name
	 * @return
	 */
	public static Str2Enum getStr2EnumByName(String columnName){
		return Str2Enum.valueOf(columnName);
	}
	/**
	 * 根据索引数返回枚举类型
	 * @param index
	 * @return
	 */
	public static Str2Enum getStr2EnumByIndex(int index){
		return Str2Enum.values()[index];
	}
	
	public static void main(String[] args) {
		System.out.println("输出枚举名字:"+Str2Enum.ACTIVE);
		System.out.println("输出枚举key:"+Str2Enum.ACTIVE.getKey());
		System.out.println("输出枚举value:"+Str2Enum.ACTIVE.getValue());
		System.out.println("根据 value 值获取枚举:"+Str2Enum.getStr2EnumByValue("冻结"));
		System.out.println("根据 key 值获取枚举:"+Str2Enum.getStr2EnumByKey("init"));
		System.out.println("根据序数获取枚举:"+Str2Enum.getStr2EnumByIndex(0));
		System.out.println("根据 枚举名字 值获取枚举:"+Str2Enum.getStr2EnumByName("INIT"));
	}
	
}
关键一环-实现 TypeHandler

如果你对代码逻辑有疑问,请参考本文中关于源码的类的内容
由于存在自定义内容,你也需要参考枚举类中的静态方法
数据库的值-对应枚举类的那个值-静态方法转化为枚举类型
枚举类型-对应枚举的某个值-数据库中的值

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

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;

import com.bestcxx.stu.springmybatis.enums.Str2Enum;

public class Str2EnumTypeHandler implements TypeHandler<Str2Enum> {
	
	@Override
	public void setParameter(PreparedStatement ps, int i, Str2Enum parameter, JdbcType jdbcType) throws SQLException {
		//比如我们希望存储的是枚举类型的 key
		ps.setString(i, parameter.getKey());
	}

	@Override
	public Str2Enum getResult(ResultSet rs, String columnName) throws SQLException {
		//获取数据库中的值
		String key=rs.getString(columnName);
		//根据之前存储的规则,这个值是 枚举 的 key ,所以根据枚举的key获取枚举
		return Str2Enum.getStr2EnumByKey(key);
	}

	@Override
	public Str2Enum getResult(ResultSet rs, int columnIndex) throws SQLException {
		//获取数据库中的值
		String key =rs.getString(columnIndex);
		//根据之前存储的规则,这个值是 枚举 的 key ,所以根据枚举的key获取枚举
		return Str2Enum.getStr2EnumByKey(key);
	}

	@Override
	public Str2Enum getResult(CallableStatement cs, int columnIndex) throws SQLException {
		//获取数据库中的值
		String key=cs.getString(columnIndex);
		//根据之前存储的规则,这个值是 枚举 的 key ,所以根据枚举的key获取枚举
		return Str2Enum.getStr2EnumByKey(key);
	}

}
如果你喜欢使用自动生成工具
<table tableName="ENUM_DEMO" domainObjectName="EnumDemoEntity" enableCountByExample="false"     
            enableDeleteByExample="false" enableSelectByExample="false"  enableUpdateByExample="false">
        	<columnOverride column="STR2" jdbcType="VARCHAR" javaType="com.bestcxx.stu.springmybatis.enums.Str2Enum" typeHandler="com.bestcxx.stu.springmybatis.typehandler.Str2EnumTypeHandler"></columnOverride>
        </table>
xml
<result column="STR2" property="str2" jdbcType="VARCHAR" typeHandler="com.bestcxx.stu.springmybatis.typehandler.Str2EnumTypeHandler" />
    
 #{str2,jdbcType=VARCHAR,typeHandler=com.bestcxx.stu.springmybatis.typehandler.Str2EnumTypeHandler},
测试
@Test
	public void test(){
		EnumDemoEntity record=new EnumDemoEntity();
		record.setId(1l);
		record.setStr2(Str2Enum.INIT);
		enumDemoEntityMapper.insert(record);
	System.out.println(enumDemoEntityMapper.selectByPrimaryKey(1l).getStr2().toString());
	}
结果

在这里插入图片描述

配置 typeHandler 的其他方式

这里我们使用了直接在具体属性上指定 typeHandler 的方式,我觉得这是最简单的,但是比如你有其他的需求,对于字符串类型的所有字段都有一个需求,比如加密,你不希望每一个字段都写一下,那么就可以采取其他方法了。

在实现类增加标注
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
@MappedTypes(String.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class Str2EnumTypeHandler implements TypeHandler<Str2Enum> {//内容略}
增加 Mybatis 配置
<typeHandlers>
		<typeHandler handler="com.bestcxx.stu.springmybatis.typehandler.Str2EnumTypeHandler"/>
	</typeHandlers>
指定属性的 jdbcType 和 javaType

这个需要在 xml 映射文件配置了,两个都指定,Mybatis 如果匹配到两个类型和具有 @MappedTypes、@MappedJdbcTypes 注解一致到类型就会自动调用对应到类型控制了。

如果使用匹配模式调用 typeHandler ,多个满足条件的 typeHandler 是什么关系?

根据实验,会调用最后一个

<typeHandlers>
		<typeHandler handler="com.bestcxx.stu.springmybatis.typehandler.Str2EnumTypeHandler2"/>
		<typeHandler handler="com.bestcxx.stu.springmybatis.typehandler.Str2EnumTypeHandler"/>
	</typeHandlers>

猜你喜欢

转载自blog.csdn.net/bestcxx/article/details/85016413