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 | | +------------+-------------+------+-----+---------+----------------+
能夠看到,自定義的類型處理器已經正常工做了。