MyBatis:自定義類型轉換器(typeHandlers)

MyBatis定義了一些默認處理器,能夠用來設置參數或取結果集時實現自動轉換,有些類型MyBatis是不支持的,例如Java 8中的日期類型,本文將介紹如何定義自定義類型處理器,來知足最新的日期類型。java

一. 新建數據庫表students,包含time和date類型,我用的是MySql數據庫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類sql

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類,下面將新建兩個類型處理器,分別用這兩種方式來實現。shell

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 類型的類型處理器,採用的是繼承類的方式apache

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();
        }
    }
}


注:無論是實現的方式仍是繼承的方式,在設置參數或獲取結果集時,都應該考慮空值的狀況,不然在空值上調用方法將拋異常!!!
session


四. 在mybatis.xml配置文件中,註冊新建的類型處理器mybatis

1. 能夠使用批量註冊的方式app

<configuration>
	<typeHandlers>
	    <!-- 使用package元素將掃描 cn.kolbe.mybatis.type 包下的所有類型處理器 -->
    	    <package name="cn.kolbe.mybatis.type"/>
  	</typeHandlers>
</configuration>

2. 也能夠使用一個一個註冊的方式,不過麻煩一些ide

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

能夠看到,自定義的類型處理器已經正常工做了。

相關文章
相關標籤/搜索