03类型处理器及源码分析(模板设计模式)

1简介

在java中存在int,String,byte等各种类型的数据,数据库中存在int,varchar,tinyint等类型的数据,作为ORM框架,Mybatis处理了一些常用的Java对象和数据库关系之间的映射

无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器(截取部分)。

1.1typeHandlers标签

你可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型。具体做法为:实现org.apache.ibatis.type.TypeHandler 接口, 或继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler, 然后可以选择性地将它映射到一个JDBC类型。

需求:将实体类User表中的添加日期字段,存储数据库时存储为字符串

 ①user表添加日期字段

 

 ②修改mybatis核心配置文件mybatis-config.xml添加注册类型处理器

  <!--注册类型处理器-->
    <typeHandlers>
        <typeHandler handler="com.nie.handler.DateTypeHandler"></typeHandler>
    </typeHandlers>

③自定义转换类继承类BaseTypeHandler<T>

package com.nie.handler;

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

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class DateTypeHandler extends BaseTypeHandler<LocalDateTime> {
    //将java类型 转换成 数据库需要的类型
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, LocalDateTime localDateTime, JdbcType jdbcType) throws SQLException {
        // 时间格式化①
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String timeFormat = dateTimeFormatter.format(localDateTime);
        preparedStatement.setString(i,timeFormat);
    }
    //将数据库中类型 转换成java类型
    //String参数  要转换的字段名称
    //ResultSet 查询出的结果集
    @Override
    public LocalDateTime getNullableResult(ResultSet resultSet, String s) throws SQLException {
        String timeStr = resultSet.getString(s);
        LocalDateTime dateTime = LocalDateTime.parse(timeStr,DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        return dateTime;
    }
    //将数据库中类型 转换成java类型
    @Override
    public LocalDateTime getNullableResult(ResultSet resultSet, int i) throws SQLException {
        String timeStr = resultSet.getString(i);
        LocalDateTime dateTime = LocalDateTime.parse(timeStr,DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        return dateTime;
    }
    //将数据库中类型 转换成java类型
    @Override
    public LocalDateTime getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        String timeStr = callableStatement.getString(i);
        LocalDateTime dateTime = LocalDateTime.parse(timeStr,DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        return dateTime;
    }

}

④编写usermapper配置文件和接口 插入和查询方法

package com.nie.mapper;
import com.nie.pojo.User;
import java.util.List;

public interface UserMapper {
    public User findById(int id);
    public void insertUser(User user);


}
<?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.nie.mapper.UserMapper">
    <select id="findById" resultType="com.nie.pojo.User" parameterType="int">
        select * from user where id=#{id}
    </select>

    <insert id="insertUser" parameterType="com.nie.pojo.User">
        insert into user(id,username,password,birthday) values (#{id},#{username},#{password},#{birthday})
    </insert>
 
</mapper>

⑤测试代码

package com.nie;

import com.nie.mapper.UserMapper;
import com.nie.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;


public class DateTypeHandlerTest {
    @Test
    public void test01() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession session = sqlSessionFactory.openSession(true);//开启事务 默认是关闭的
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setUsername("liubei");
        user.setPassword("llll");
        user.setBirthday(LocalDateTime.now());
        mapper.insertUser(user);
        session.close();
    }
    @Test
    public void test02() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession session = sqlSessionFactory.openSession(true);//开启事务 默认是关闭的
        UserMapper mapper = session.getMapper(UserMapper.class);
        System.out.println(mapper.findById(5));
        session.close();
    }
}

测试结果
插入方法数据库正常显示转换器类转换后的结果

 查询方法数据显示时间类型

2BaseTypeHandler<T>源码阅读

如要加深理解可查看以下内容,

2.1模板设计模式

模板设计模式中模板规定了大体的框架,只留下一些细节供使用者来修改和完善。使用同一模板做出的不同产品都具有一致的框架

在模板模式种,需要使用一个抽奖类定义一套操作的整体步骤(即模板),而抽象类的子类完成每个步骤的具体实现。这样,抽象类的不同子类遵循了同样的一套模板

如以下代码

模板父类:打扫卫生

package com.nie;

/**
 * 打扫卫生模板,为所有的打扫卫生工作定义四个大步骤:准备、实施、善后、汇报
 */
//模板模式父类
public abstract class Clean {
    public void clean(){

    }
    abstract void prepare();//准备
    abstract void implment();//实施
    abstract void windup();//善后
    void report(){//汇报
        System.out.println("告诉别人已经打扫完成");
    }

}

擦玻璃实现类

package com.nie;

/**
 * 擦玻璃实现类
 */

public class WipeGlass extends Clean{
    @Override
    void prepare() {
        System.out.println("找到抹布,清洗抹布");
    }

    @Override
    void implment() {
        System.out.println("擦玻璃");
    }

    @Override
    void windup() {
        System.out.println("清理窗台");

    }
}

 擦黑板实现类

package com.nie;

/**
 * 擦黑板实现类
 */

public class WipeBlackboard extends Clean{
    @Override
    void prepare() {
        System.out.println("找到黑板擦");
    }

    @Override
    void implment() {
        System.out.println("擦黑板");
    }

    @Override
    void windup() {
        System.out.println("清理粉笔");
    }
}

2.2mybatis源码阅读

涉及到的核心类:BaseTypeHandler,TypeReference,TypeHandler

本次查看源码mybatis版本是3.4.5,每个版本会有细微的区别,但是核心都是相似的

接口TypeHandler<T>定义了几个抽象方法,BaseTypeHandler<T>实现了该接口

模板模式基类BaseTypeHandler<T>是所有类型处理器的父类,定义了模板的框架,mybatis框架和自定义模板类实现了该基类方法的细节

采用泛型,让子类定义自己的类型

mybatis框架的实现类都在org.apache.ibatis.type包下

还有jdk8版本的时间类型处理器,上文案例就是处理时间,业务效果是相同的,开发人员可以根据自己需求添加功能

其他的实现类就不在展示

查看IntegerTypeHandler和LocalDateTimeTypeHandler的实现类都继承了模板基BaseTypeHandler

 

如果想更深入了解模板设计模式查看该文章模板方法模式_梓源先生的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值