文档章节

MyBatis:自定义类型转换器(typeHandlers)

kolbe
 kolbe
发布于 2015/09/18 15:35
字数 1005
阅读 2120
收藏 7

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    |                |
+------------+-------------+------+-----+---------+----------------+

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




© 著作权归作者所有

kolbe
粉丝 120
博文 20
码字总数 21363
作品 0
成都
程序员
私信 提问
Mybatis3.3.x技术内幕(十二):Mybatis之TypeHandler

Mybatis中的TypeHandler有两个功能,一个是完成javaType至jdbcType的转换,另外一个是完成jdbcType至javaType的转换。 public interface TypeHandler<T> { void setParameter(PreparedStatem......

祖大俊
2016/05/06
991
0
mybatis学习笔记(5)-SqlMapConfig

mybatis学习笔记(5)-SqlMapConfig 标签: mybatis [TOC] 本文主要讲解SqlMapConfig配置文件 > 参考mybatis – MyBatis 3 Configuration SqlMapConfig.xml中配置的内容和顺序如下 properties......

brianway
2016/02/28
124
0
mybatis系列-2-自定义typyHandler

注册typeHandler 注册TypeHandler 建立了自己的TypeHandler之后就需要把它注册到Mybatis的配置文件中,让Mybatis能够识别并使用它。注册TypeHandler主要有两种方式,一种是通过在Mybatis配置...

嘿嘿!!
2016/11/10
0
0
MyBatis 3.4.1 和 TypeHandlers-JSR310 1.0.1 发布

MyBatis 3.4.1 和 TypeHandlers-JSR310 1.0.1 发布了,更新如下: MyBatis 3.4.1 包括四个用户可见的改进: Allow referencing parameters by their declared names when compiled with Java......

oschina
2016/06/27
3.4K
3
基于注解的Mybatis mapper 接口注意事项

原文:http://my.oschina.net/doctor2014/blog/411580 基于注解的Mybatis mapper 接口功能没有mapper xml配置文件丰富,而且动态sql语句的灵活性不能和xml配置相比。 这里只说一下基于注解的...

Beaver_
2015/05/06
7.6K
2

没有更多内容

加载失败,请刷新页面

加载更多

技术复习-Spring事务

spring事务 1.事务传播机制 在spring中事务存在嵌套的情况,在这种情况下事务如何协调,spring在TransactionDefinition中设了七个规则,被称作事务的传播机制 1.TransactionDefinition.PROP...

Lubby
22分钟前
1
0
linux 虚拟机安装

一、虚拟化检查 1. 检查cpu是否支持 grep -E 'vmx|svm' /proc/cpuinfo 2. 检查虚拟化是否开启 lsmod |grep kvm 显示内容与截图一致,服务器已经开启了虚拟化的支持,如果没有前2条内容,...

小儿
22分钟前
2
0
Linux之系统日志简介

前言 日志在排查文件的时候至关重要,在Linux上一般跟系统相关的日志默认都会放到/var/log下面。 1、/var/log/boot.log 一般包含系统启动时的日志,包括自启动的服务。 2、/var/log/btmp 记录...

城市之雾
23分钟前
1
0
Android数据存储2 文件存储

1.内部存储(私有的,其他程序不能获取) a. 存:FileOutputStream fos = openFileOutput("file", MODE_PRIVATE); 读: FileInputStream fis = openFileInput("file"); 文件路径:data/data/当......

Coding缘
23分钟前
1
0
23种设计模式全解析

一、设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理...

嘿嘿嘿IT
24分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部