Mybatis——TypeHandler 你的名字 2022-03-22 02:02 269阅读 0赞 使用mybatis时,一般情况下是不需要考虑数据库中的数据类型和java数据类型之间的转换的,因为有很多内置的TypeHandler帮助我们做了转换这件事,内置TypeHandler如下 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hjcncwMQ_size_16_color_FFFFFF_t_70][] 上面都是mybatis内置的处理器,所以在平时开发的时候我们不用去关心java到数据库的类型转化关系,mybatis都帮我们把这些工作完成了。但这并不是我们要关心的重点,我们需要的是自定义TypeHandler去应对更多的需求。 ## **本案例演示将List直接存入数据库中** ## # 自定义TypeHandler # 新建一个Player对象 ![20190125121708585.png][] 数据库表结构 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hjcncwMQ_size_16_color_FFFFFF_t_70 1][] 要把Player中的List存到数据库中的varchar中,mybatis内置的TypeHandler是实现不了的,所以我们自定义TypeHandler. 第一步:实现 TypeHandler<T> 接口,T是 javaType -- jdbcType中的javaType,在本次案例中,T是List<String> public class ListTypeHandler implements TypeHandler<List<String>> { public void setParameter(PreparedStatement preparedStatement, int i, List<String> strings, JdbcType jdbcType) throws SQLException { String join = StringUtils.join(strings, ","); preparedStatement.setString(i, join); } public List<String> getResult(ResultSet resultSet, String s) throws SQLException { return Arrays.asList(resultSet.getString(s).split(",")); } public List<String> getResult(ResultSet resultSet, int i) throws SQLException { return Arrays.asList(resultSet.getString(i).split(",")); } public List<String> getResult(CallableStatement callableStatement, int i) throws SQLException { String hobbys = callableStatement.getString(i); return Arrays.asList(hobbys.split(",")); } } 还可以添加自定义注解通过注解配置java类型和jdbc类型: (加了注解,在配置文件中就不用配置jdbcType和javaType了,不加注解的话就要在配置文件中配清楚) @MappedTypes() :注解配置java类型 @MappedJdbcTypes(): 注解配置jdbc类型 第二步:编写Dao接口 public interface PlayerDao { void savePlayer(Player player); Player selectPlayerById(Integer id); void updatePlayerById(Player player); } 第三步:编写Mapper映射文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.typehandler.test.dao.PlayerDao"> <resultMap id="Player" type="com.typehandler.test.bean.Player"> <id property="id" column="id"></id> <result column="name" property="name"></result> <result column="hobbies" property="hobbies" typeHandler="com.typehandler.test.typehandler.ListTypeHandler"></result> </resultMap> <insert id="savePlayer" parameterType="com.typehandler.test.bean.Player" > insert into player(name,hobbies) values(#{name},#{hobbies,typeHandler=com.typehandler.test.typehandler.ListTypeHandler}) </insert> <select id="selectPlayerById" parameterType="java.lang.Integer" resultMap="Player"> select * from player where id = #{id} </select> <update id="updatePlayerById" parameterType="com.typehandler.test.bean.Player" > update player set name=#{name} , hobbies = #{hobbies,typeHandler=com.typehandler.test.typehandler.ListTypeHandler} where id = #{id} </update> </mapper> 在resultMap中指定typeHandler就可以使用类型转换了,但是这只能在查询中生效。 如果想在插入或者更新时也使用typeHandler有三种方式,需要在insert或update的标签中 1.指定 TypeHandler <insert id="savePlayer" parameterType="com.typehandler.test.bean.Player" > insert into player(name,hobbies) values(#{name},#{hobbies,typeHandler=com.typehandler.test.typehandler.ListTypeHandler}) 2.指定jdbcType和javaType(需要在配置文件中配置typeHandler) <insert id="savePlayer" parameterType="com.typehandler.test.bean.Player" > insert into player(name,hobbies) values(#{name},#{hobbies,javaType=List,jdbcType=VARCHAR}) </insert> 3.TypeHandler和jdbcType和javaType同时指定。 <insert id="savePlayer" parameterType="com.typehandler.test.bean.Player" > insert into player(name,hobbies) values(#{name},#{hobbies,javaType=List,jdbcType=VARCHAR,typeHandler=com.typehandler.test.typehandler.ListTypeHandler}) </insert> ## 目前来看当在配置文件中配置了typeHandler的唯一作用是在只指定javaType和jdbcType时能够找到对应的转换器 ## <typeHandlers> <typeHandler jdbcType="VARCHAR" javaType="java.util.List" handler="com.typehandler.test.typehandler.ListTypeHandler"/> </typeHandlers> 测试代码及结果 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hjcncwMQ_size_16_color_FFFFFF_t_70 2][] # 再写一个把Enum存储为varchar的typeHandler,继承自BaseTypeHandler # 实体类: public class MyUser { private Integer id; private String name; private MyEnum myEnum; public MyUser(Integer id, String name, MyEnum myEnum) { this.id = id; this.name = name; this.myEnum = myEnum; } public MyUser() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public MyEnum getMyEnum() { return myEnum; } public void setMyEnum(MyEnum myEnum) { this.myEnum = myEnum; } @Override public String toString() { return "MyUser{" + "id=" + id + ", name='" + name + '\'' + ", myEnum=" + myEnum + '}'; } } 枚举: public enum MyEnum { NORMAL(1, "正常"), DELETE(0, "删除"), CANCEL(2, "注销"); private int code; private String status; MyEnum(int code, String status) { this.code = code; this.status = status; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public static MyEnum Value2MyEnum(int code) { for (MyEnum myEnum : MyEnum.values()) { if (myEnum.code == code) { return myEnum; } } throw new IllegalArgumentException("无效的value值: " + code + "!"); } } TypeHandler: public class EnumTypeHandler extends BaseTypeHandler<MyEnum> { public void setNonNullParameter(PreparedStatement preparedStatement, int i, MyEnum myEnum, JdbcType jdbcType) throws SQLException { preparedStatement.setInt(i, myEnum.getCode()); } public MyEnum getNullableResult(ResultSet resultSet, String s) throws SQLException { return MyEnum.Value2MyEnum(resultSet.getInt(s)); } public MyEnum getNullableResult(ResultSet resultSet, int i) throws SQLException { return MyEnum.Value2MyEnum(resultSet.getInt(i)); } public MyEnum getNullableResult(CallableStatement callableStatement, int i) throws SQLException { return MyEnum.Value2MyEnum(callableStatement.getInt(i)); } } xml映射文件,节选 <resultMap id="MyUser" type="com.typehandler.test.bean.MyUser"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="status" property="myEnum"/> </resultMap> <insert id="saveMyUser" parameterType="com.typehandler.test.bean.MyUser"> insert into my_user(name,status) values (#{name},#{myEnum,typeHandler=com.typehandler.test.typehandler.EnumTypeHandler}); </insert> <select id="selectMyUserById" parameterType="java.lang.Integer" resultMap="MyUser"> select * from my_user where id = #{id} </select> mybatis配置文件节选 <typeHandlers> <typeHandler jdbcType="VARCHAR" javaType="java.util.List" handler="com.typehandler.test.typehandler.ListTypeHandler"/> <typeHandler handler="com.typehandler.test.typehandler.EnumTypeHandler"/> </typeHandlers> 存储的时候,存储枚举的key,读取的时候,拿到Key要返回枚举,所以在枚举类中加一个转换方法。 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hjcncwMQ_size_16_color_FFFFFF_t_70]: /images/20220322/b6b856ed7c2248ae86d6bf4530e150cd.png [20190125121708585.png]: /images/20220322/76c0141ca8f64717b7ebeb8c3eb463ae.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hjcncwMQ_size_16_color_FFFFFF_t_70 1]: /images/20220322/b148612f53304fc5b16313179a504df4.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hjcncwMQ_size_16_color_FFFFFF_t_70 2]: /images/20220322/4f0f7cb5f0cb4a2085779c450d6661dc.png
还没有评论,来说两句吧...