为什么80%的码农都做不了架构师?>>>
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{
@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 {
@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. 可以使用批量注册的方式
2. 也可以使用一个一个注册的方式,不过麻烦一些
五. StudentMapper.xml文件中配置相关映射信息
六. 可以开始使用,直接测试从数据库中获取单个记录是否已经自动转换
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 | |
+------------+-------------+------+-----+---------+----------------+
可以看到,自定义的类型处理器已经正常工作了。