在 Java 实体类中,定义时间的属性一般是Date 类型,但数据库中却是字符串类型,每次查询、新增等操作都要做类型转换,但如果使用 Mybatis 提供的自定义 TypeHandler 的功能就能完美的解决这个问题。
实体类User.java
package com.lks.domain;
import java.io.Serializable;
import java.util.Date;
/**
* Created by likaisong on 2019/2/24.
*/
public class User implements Serializable {
private int id;
private String name;
private int age;
private String county;
private Date date;
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getCounty() {
return county;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setCounty(String county) {
this.county = county;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date= date;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", age=" + age + ", county=" + county + ", date=" + date + "]";
}
}
自定义TypeHandle,有两种实现方式:直接实现 TypeHandler 也可以继承 BaseTypeHandler,这里我选择直接实现 TypeHandler :
DateToStringTypeHandler.java
package com.lks.handler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Created by likaisong on 2019/2/25.
*/
public class DateToStringTypeHandler implements TypeHandler{
/**
* 将时间戳传入数据库
* @param preparedStatement
* @param i
* @param o
* @param jdbcType
* @throws java.sql.SQLException
*/
@Override
public void setParameter(PreparedStatement preparedStatement, int i, Object o, JdbcType jdbcType) throws SQLException {
Date date = (Date) o;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format(date);
preparedStatement.setString(i, dateString);
}
/**
* 将字符串类型的时间戳转换为Date
* @param resultSet
* @param s
* @return
* @throws SQLException
*/
@Override
public Object getResult(ResultSet resultSet, String s) throws SQLException {
String timeStr = resultSet.getString(s);
if (timeStr != null || "".equals(timeStr)){
return stringToDate(timeStr);
}
return null;
}
@Override
public Object getResult(ResultSet resultSet, int i) throws SQLException {
String timeStr = resultSet.getString(i);
if (timeStr != null || "".equals(timeStr)){
return stringToDate(timeStr);
}
return null;
}
@Override
public Object getResult(CallableStatement callableStatement, int i) throws SQLException {
String timeStr = callableStatement.getString(i);
if (timeStr != null || "".equals(timeStr)){
return stringToDate(timeStr);
}
return null;
}
private Date stringToDate(String timeStr) {
if (timeStr != null || "".equals(timeStr)) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ParsePosition pos = new ParsePosition(0);
Date date = formatter.parse(timeStr, pos);
return date;
}
return null;
}
}
mybatis配置文件中配置自定义typeHandler,主要看typeHandler标签:
mybatis-config:
mapper文件中新增或查询操作:
insert into users (id, name, age, county, date)
values (#{id},#{name},#{age},#{county},#{date, typeHandler=com.lks.handler.DateToStringTypeHandler})
新增数据的操作只要对需要进行类型转换的字段添加相关配置即可,但查询操作需要借助resultMap来实现转换。
对操作执行测试方法:
TestMain.java
package com.lks.test;
import com.lks.domain.User;
import com.lks.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.testng.annotations.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
/**
* Created by likaisong on 2019/2/24.
*/
public class TestMain {
private static SqlSession getSqlSession(String resource){
if (resource == null || "".equals(resource)){
return null;
}
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
return session;
}
@Test
public static void testDateToString(){
String resource = "mybatis-config.xml";
SqlSession session = getSqlSession(resource);
try {
String statement = "userMapper.dateToString";
User user = new User();
user.setName("阿飞");
user.setAge(20);
user.setCounty("中国");
user.setDate(new Date());
session.insert(statement, user);
session.commit();
System.out.println("插入数据后返回的自增ID:" + user.getId());
} finally {
session.close();
}
}
@Test
public static void testStringToDate(){
String resource = "mybatis-config.xml";
SqlSession session = getSqlSession(resource);
try {
//先插入一条数据
String insertStatement = "userMapper.dateToString";
User user = new User();
user.setName("阿飞");
user.setAge(20);
user.setCounty("中国");
user.setDate(new Date());
session.insert(insertStatement, user);
session.commit();
System.out.println("插入数据后返回的自增ID:" + user.getId());
//查询刚插入的数据
String selectStatement = "userMapper.stringToDate";
User resUser = session.selectOne(selectStatement, user.getId());
System.out.println(resUser);
} finally {
session.close();
}
}
}
通过查表或由直接打印出来对内容可以看到时间字段可以在Date和String中实现灵活准换,自定义的 TypeHandler 也经常用来解决项目中的枚举类型,也是比较方便的。