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

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

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添加注册类型处理器

  
    
        
    

③自定义转换类继承类baseTypeHandler

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 {
    //将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);


}




    
        select * from user where id=#{id}
    

    
        insert into user(id,username,password,birthday) values (#{id},#{username},#{password},#{birthday})
    
 


⑤测试代码

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源码阅读

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

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定义了几个抽象方法,baseTypeHandler实现了该接口

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

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

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

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

其他的实现类就不在展示

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

 

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5522917.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-13
下一篇 2022-12-13

发表评论

登录后才能评论

评论列表(0条)

保存