MyBatis学习笔记(二):创建自定义类型处理器

MyBatis定义了一些默认处理器,可以用来设置参数或取结果集时实现自动转换,有些类型MyBatis是不支持的,例如Java 8中的日期类型,本文将介绍如何定义自定义类型处理器,来满足最新的日期类型。

一. 新建数据库表students,包含time和date类型,我用的是MySql数据库

-- 创建students示例表
create table students (
    id int primary key auto_increment,
    name varchar(20),
    createDate date,
    createTime time
)

-- 插入一条示例数据
insert into students(name, createDate, createTime) values(‘kolbe‘, ‘2015-09-18‘, ‘15:00:00‘);

二. 创建对应数据库表的Student类

package cn.kolbe.mybatis.bean;

public class Student {
	private int id;
	private String name;
	private LocalDate createDate;
	private LocalTime createTime;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public LocalTime getCreateTime() {
		return createTime;
	}
	public void setCreateTime(LocalTime createTime) {
		this.createTime = createTime;
	}
	public LocalDate getCreateDate() {
		return createDate;
	}
	public void setCreateDate(LocalDate createDate) {
		this.createDate = createDate;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", createDate=" + createDate + ", createTime=" + createTime
				+ "]";
	}
}

三. 新建类型处理器,有两种做法:实现org.apache.ibatis.type.TypeHandler接口,或继承org.apache.ibatis.type.BaseTypeHandler类,下面将新建两个类型处理器,分别用这两种方式来实现。

1. 支持 java.time.LocalTime 类型的类型处理器,采用的是实现接口的方式

package cn.kolbe.mybatis.type;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.time.LocalTime;

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

@MappedTypes(LocalTime.class)
public class LocalTimeTypeHandler implements TypeHandler<LocalTime>{
	@Override
	public void setParameter(PreparedStatement ps, int i, LocalTime parameter, JdbcType jdbcType) throws SQLException {
		if(parameter == null) {
			ps.setTime(i, null);
		} else {
			ps.setTime(i, Time.valueOf(parameter));
		}
	}

	@Override
	public LocalTime getResult(ResultSet rs, String columnName) throws SQLException {
		Time time = rs.getTime(columnName);
		return time == null ? null : time.toLocalTime();
	}

	@Override
	public LocalTime getResult(ResultSet rs, int columnIndex) throws SQLException {
		Time time = rs.getTime(columnIndex);
		return time == null ? null : time.toLocalTime();
	}

	@Override
	public LocalTime getResult(CallableStatement cs, int columnIndex) throws SQLException {
		Time time = cs.getTime(columnIndex);
		return time == null ? null : cs.getTime(columnIndex).toLocalTime();
	}
}

2. 支持 java.time.LocalDate 类型的类型处理器,采用的是继承类的方式

package cn.kolbe.mybatis.type;

import java.sql.CallableStatement;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;

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

@MappedTypes(LocalDate.class)
public class LocalDateTypeHandler extends BaseTypeHandler<LocalDate> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, LocalDate parameter, JdbcType jdbcType) throws SQLException {
    	ps.setDate(i, Date.valueOf(parameter));
    }

    @Override
    public LocalDate getNullableResult(ResultSet rs, String columnName) throws SQLException {
        Date date = rs.getDate(columnName);
        if (date == null) {
            return null;
        } else {
            return date.toLocalDate();
        }
    }

    @Override
    public LocalDate getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        Date date = rs.getDate(columnIndex);
        if (date == null) {
            return null;
        } else {
            return date.toLocalDate();
        }
    }

    @Override
    public LocalDate getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        Date date = cs.getDate(columnIndex);
        if (date == null) {
            return null;
        } else {
            return date.toLocalDate();
        }
    }
}

注:不管是实现的方式还是继承的方式,在设置参数或获取结果集时,都应该考虑空值的情况,否则在空值上调用方法将抛异常!!!

四. 在mybatis.xml配置文件中,注册新建的类型处理器

1. 可以使用批量注册的方式

<configuration>
	<typeHandlers>
	    <!-- 使用package元素将扫描 cn.kolbe.mybatis.type 包下的全部类型处理器 -->
    	    <package name="cn.kolbe.mybatis.type"/>
  	</typeHandlers>
</configuration>

2. 也可以使用一个一个注册的方式,不过麻烦一些

<configuration>
	<typeHandlers>
    	<typeHandler handler="cn.kolbe.mybatis.type.LocalDateTypeHandler"/>
    	<typeHandler handler="cn.kolbe.mybatis.type.LocalTimeTypeHandler"/>
  	</typeHandlers>
</configuration>

五. StudentMapper.xml文件中配置相关映射信息

<?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="cn.kolbe.mybatis.config.StudentMapper">
	<select id="getStudent" parameterType="int" resultType="cn.kolbe.mybatis.bean.Student">
		select * from students where id = #{id}
	</select>
</mapper>

六. 可以开始使用,直接测试从数据库中获取单个记录是否已经自动转换

public class StudentDao {
	@Test
	public void testGetStudent2() throws Exception {
		SqlSession session = null;
		try {
			// 从Factory类(一个简单的类就不上代码了)中获取SqlSessionFactory实例,并获取SqlSession实例
			session = Factory.getFactory().openSession();
			String statement = "cn.kolbe.mybatis.config.StudentMapper.getStudent";
			Student student = session.selectOne(statement, 1);
			System.out.println(student.getCreateDate().getClass());
			System.out.println(student.getCreateTime().getClass());
			System.out.println(student);
		} finally {
			session.close();
		}
	}
}

查看控制台输出信息:

class java.time.LocalDate
class java.time.LocalTime
Student [id=1, name=kolbe, createDate=2015-09-18, createTime=15:00]

可以再看下数据库students表结构:

mysql> describe students;
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | int(11)     | NO   | PRI | NULL    | auto_increment |
| name       | varchar(50) | YES  |     | NULL    |                |
| createDate | date        | YES  |     | NULL    |                |
| createTime | time        | YES  |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+

可以看到,自定义的类型处理器已经正常工作了。

时间: 2024-10-31 21:39:54

MyBatis学习笔记(二):创建自定义类型处理器的相关文章

Haskell学习笔记二:自定义类型

内容提要: 代数数据类型 - Algebraic Data Types: 自定义数据类型 - data关键字:值构造器:类型变量与类型构造器: 记录(Record)语法 - 简化自定义数据类型的一种语法糖: 一个完整的例子 - PurchaseOrder定义和简单计算.单元测试: 代数数据类型(Algebraic Data Types) 为什么Haskell的数据类型会有代数数据类型这个名字?回想我们初中时代,初次学习代数的情况,印象最深刻就是x,y,z代替了具体的数字,引入方程式的概念,对 解

Go语言学习笔记(二) [变量、类型、关键字]

日期:2014年7月19日 1.Go 在语法上有着类 C 的感觉.如果你希望将两个(或更多)语句放在一行书写,它们 必须用分号分隔.一般情况下,你不需要分号. 2.Go 同其他语言不同的地方在于变量的类型在变量名的后面.例如:不是,int a,而是 a int.当定义了一个变量,它默认赋值为其类型的 null 值.这意味着,在 var a int后,a 的 值为 0.而 var s string,意味着 s 被赋值为零长度字符串,也就是 "". 3.Go语言的变量声明和赋值 在Go中使

mybatis学习笔记(二)-- 使用mybatisUtil工具类体验基于xml和注解实现

项目结构  基础入门可参考:mybatis学习笔记(一)-- 简单入门(附测试Demo详细过程) 开始体验 1.新建项目,新建类MybatisUtil.java,路径:src/util/MybatisUtil.java package util; import java.io.InputStream; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; i

MyBatis学习笔记(二) 关联关系

今天主要学习的关联关系是一对一关系与一对多关系. 一.一对一关系 还是通过例子来解释说明.(一个妻子对应一个丈夫). 1)数据库信息 1 create table t_wife( 2 id int primary key auto_increment, 3 wife_name varchar(20), 4 fk_husband_id int 5 ); 6 7 create table t_husband( 8 id int primary key auto_increment, 9 husban

MyBatis学习笔记二:MyBatis生产中使用环境搭建

这里是在上一个环境的基础上修改的,这里就不在给出所有的配置,只给出哪里修改的配置 1.修改POJO对象为注解方式 2.创建Dao层接口 package com.orange.dao; import com.orange.model.Person; public interface PersonDao { // 这里的返回值和方法名必须和PersonMapper.xml中定义的执行语句的id一致 public Person selectPerson(); } 3.修改PersonMapper.xm

MSMQ学习笔记二——创建Message Queue队列

一.创建Message Queue队列的主要流程 1.定义MQQUEUEPROPS 结构: 2.设置消息队列属性: 3.初始化MQQUEUEPROPS 结构: 4.调用MQCreateQueue创建队列. 下面对MSDN上的创建Message Queue队列示例函数: HRESULT CreateMSMQQueue( LPWSTR wszPathName, PSECURITY_DESCRIPTOR pSecurityDescriptor, LPWSTR wszOutFormatName, DWO

mybatis学习笔记二mybatis结合spring mvc实现(用户登录,数据查询)

接着上次的来,我做了一个用户登录的例子 UserController: package com.yihaomen.controller; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.spring

Quick cocos2dx-Lua(V3.3R1)学习笔记(二)----创建新项目

打开player,我们点击[新建项目]看到 第一个输入框是输入我们项目路径 第二个输入包的名字(com.公司名.gamges.项目名称) ok,填写完毕,右下角创建项目吧 .........................控制台输出结束,我们发现Create Project按钮变成Open了. 点击open,我们查看效果 果然,你们真的逃脱不了这个梗吗?Hello World,不能换点其他玩意么,比如 你吃了么O(∩_∩)O 是不是觉得这个窗口超级大啊,我的眼睛难以承受啊, 点击view按钮,里

python学习笔记07:自定义类型

class person: def __init__(self,name,age,weight): self.name = name self.age = age self.weight = weight def SayHi(self): print('Hi %s' % (self.name)) def ToString(self): return 'name: %s \nage: %d \nweight: %d \n' % (self.name, self.age, self.weight)