在大学写web应用的时候经常会遇到这么个问题,当我要插入一条数据,某个数据是Date类型,数据库中却是VARCHAR类型,这个时候可能会傻乎乎的先把这个数据自己手动转换成String类型再插入到数据库中,其实大可不必。MyBatis为我们提供了更好的方法即是TypeHandler来应对Java和jdbc字段类型不匹配的情况。MyBatis中内置了不少的TypeHandler,如果我们想要自己自定义一个TypeHandler可以实现TypeHandler接口,也可以继承BaseTypeHandler类。下面我们实现一个将Java中的Date类型利用我们自定义的ExampleTypeHandler来转换为JDBC的VARCHAR类型。

  我们对MyBatis的介绍先局限在使用,在会使用过后我们再究其原理、源码。

 package day_8_mybatis.util;

 import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date; import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType; /**
* 注意在引入Date所在的包时,是java.util.Date,而不是java.sql.Date,这一点不要搞错。
* @author turbo
*
* 2016年10月23日
*/
public class ExampleTypeHandler extends BaseTypeHandler<Date> { /* 根据列名,获取可以为空的结果
* @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.ResultSet, java.lang.String)
*/
@Override
public Date getNullableResult(ResultSet rs, String columnName)
throws SQLException {
String sqlTimetamp = rs.getString(columnName);
if (null != sqlTimetamp){
return new Date(Long.valueOf(sqlTimetamp));
}
return null;
} /* 根据列索引,获取可以为空的结果
* @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.ResultSet, int)
*/
@Override
public Date getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
String sqlTimetamp = rs.getString(columnIndex);
if (null != sqlTimetamp){
return new Date(Long.valueOf(sqlTimetamp));
}
return null;
} /* * @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.CallableStatement, int)
*/
@Override
public Date getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
String sqlTimetamp = cs.getString(columnIndex);
if (null != sqlTimetamp){
return new Date(Long.valueOf(sqlTimetamp));
}
return null;
} /* 设置非空参数
* @see org.apache.ibatis.type.BaseTypeHandler#setNonNullParameter(java.sql.PreparedStatement, int, java.lang.Object, org.apache.ibatis.type.JdbcType)
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Date parameter,
JdbcType jdbcType) throws SQLException {
ps.setString(i, String.valueOf(parameter.getTime()));
} }

  我们已经自定义了一个TypeHandler,接着我们要在mybatis-config.xml中注册。

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration>
<!-- 注意configuration中各个属性配置的顺序应为:properties,settings,typeAliases,typeHandlers,objectFactory,objectWrapperFactory,reflectorFactory,plugins,environments,databaseIdProvider,mappers)-->
<properties>
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="0000"/>
</properties>
<typeHandlers>
<typeHandler handler="day_8_mybatis.util.ExampleTypeHandler" javaType="java.util.Date" jdbcType="VARCHAR"/>
</typeHandlers> <environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="day_8_mybatis/mapper/UserMapper.xml"/>
<mapper resource="day_8_mybatis/mapper/NoteMapper.xml"/>
</mappers> </configuration>

  注意各个属性配置有顺序之分,不能随意穿插。

  准备工作已经做完了,我们接着按部就班的实现POJO类 Note里面包含id和date字段。

 package day_8_mybatis.pojo;

 import java.util.Date;

 /**
* @author turbo
*
* 2016年10月23日
*/
public class Note {
private int id;
private Date date;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}

接着是负责与数据库交互Dao层的NoteMapper接口,我们只举例查询和插入。

 package day_8_mybatis.mapper;

 import day_8_mybatis.pojo.Note;

 /**
* @author turbo
*
* 2016年10月23日
*/
public interface NoteMapper {
Note queryNote(int id);
void insertNote(Note note);
}

  我们再来看看在NoteMapper.xml中是如何利用我们刚才自定义的TypeHandler。

 <?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="day_8_mybatis.mapper.NoteMapper">
<resultMap type="day_8_mybatis.pojo.Note" id="note-base">
<result property="id" column="id"/>
<result property="date" column="date" typeHandler="day_8_mybatis.util.ExampleTypeHandler"/>
</resultMap> <select id="queryNote" parameterType="int" resultMap="note-base">
select * from note where id = #{id}
</select>
<insert id="insertNote" parameterType="day_8_mybatis.pojo.Note">
insert into note (id, date) values(#{id}, #{date, typeHandler=day_8_mybatis.util.ExampleTypeHandler})  <!--使用我们自定义的TypeHandler-->
</insert>
</mapper>

  最后我们在客户端测试一下。

 package day_8_mybatis;

 import java.io.IOException;
import java.util.Date; import org.apache.ibatis.session.SqlSession; import day_8_mybatis.mapper.NoteMapper;
import day_8_mybatis.pojo.Note;
import day_8_mybatis.util.SessionFactory; /**
* 客户端
* @author turbo
*
* 2016年9月11日
*/
public class Main { /**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws Exception {
String resource = "day_8_mybatis/mybatis-config.xml"; //获取mybatis配置文件路径
SqlSession sqlSession = SessionFactory.getSqlSession(resource); //通过SessionFactory工具类(此工具类为自己构造即util包中的SessionFactory)构造SqlSession NoteMapper noteMapper = sqlSession.getMapper(NoteMapper.class); Note note = new Note();
note.setId(1);
note.setDate(new Date());
noteMapper.insertNote(note); //插入
sqlSession.commit(); //注意需要手动提交事务 note = noteMapper.queryNote(2); //查询
System.out.println(note.getDate());
} }

  注意在34行代码,需要手动提交事务,默认是关闭自动提交的,所以必须手动提交。开始没有提交事务,无论怎么都没办法插入到数据库,后来debug单步调试的时候发现了autoCommit=false,才想起来在以前大学的时候也遇到过这个这个问题所以一下就定位问题在哪儿了。

  数据库中只有一个note表,字段为id类型为int,date字段为varchar。

  至此我们就完成了自定义的TypeHandler,其实MyBatis为我们提供的TypeHandler已经不少了,不过我们还是自己试验一把,先把MyBatis学会使用,再究其原理。


这是一个能给程序员加buff的公众号

MyBatis之TypeHandler的更多相关文章

  1. Mybatis使用TypeHandler实现数据的加解密转换

    参考: MyBatis之TypeHandler: https://www.cnblogs.com/yulinfeng/p/5991170.html   前段时间收到这么个需求:为安全起见,要求在数据库 ...

  2. mybatis 枚举typeHandler

    枚举typeHandler 在绝大多数情况下,typeHandler因为枚举而使用,MyBatis已经定义了两个类作为枚举类型的支持,这两个类分别是: •EnumOrdinalTypeHandler. ...

  3. [转]Mybatis之TypeHandler使用教程

    Mybatis之TypeHandler使用教程 https://blog.csdn.net/jokemqc/article/details/81326109 深入浅出Mybatis系列(五)---Ty ...

  4. 使用Mybatis的TypeHandler加解密数据

    使用Mybatis的TypeHandler加解密数据 一.背景 二.解决方案 三.需求 四.实现思路 1.编写一个实体类,凡是此实体类的数据都表示需要加解密的 2.编写一个加解密的`TypeHandl ...

  5. 关于mybatis中typeHandler的两个案例

    在做开发时,我们经常会遇到这样一些问题,比如我有一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,怎么实现?再比如我有一个User类,User类中有一个属性叫做 ...

  6. mybatis的typeHandler

    typeHandler作用: 1.传参时将javaType类型转换成jdbcType 2.结果集中ResultSet中取值时,jdbcType转换为javaType; 系统自定义的typeHandle ...

  7. mybatis的TypeHandler 的使用

    今天看了别人的mybatis的教学视频,自己手写了一个简单的自定义的TypeHandler,有些细节记录一下. 1.定义自己的TypeHandler,代码如下: package com.example ...

  8. Mybatis自定义TypeHandler解决特殊类型转换问题

    我们知道,Java和MySQL中的数据类型是不同的,Java中除了基本数据类型,还有对象. 有时候使用MySQL存储数据,或者从MySQL中读取数据时,会有一些特殊需求

  9. 深入浅出Mybatis系列(五)---TypeHandler简介及配置(mybatis源码篇)

    上篇文章<深入浅出Mybatis系列(四)---配置详解之typeAliases别名(mybatis源码篇)>为大家介绍了mybatis中别名的使用,以及其源码.本篇将为大家介绍TypeH ...

随机推荐

  1. 跨站的艺术-XSS Fuzzing 的技巧

    作者 | 张祖优(Fooying)  腾讯云 云鼎实验室 对于XSS的漏洞挖掘过程,其实就是一个使用Payload不断测试和调整再测试的过程,这个过程我们把它叫做Fuzzing:同样是Fuzzing, ...

  2. Oracle SQL 语言分类

     Oracle SQL语句分类 2008-06-17 11:15:25 分类: Linux * 2008/06/17  星期二*蒙昭良*环境:WindowsXP + Oracle10gR2*Oracl ...

  3. Python之路-Linux命令基础(4)

    作业一: 1)开启Linux系统前添加一块大小为15G的SCSI硬盘 2)开启系统,右击桌面,打开终端 3)为新加的硬盘分区,一个主分区大小为5G,剩余空间给扩展分区,在扩展分区上划分1个逻辑分区,大 ...

  4. Java基础之J2EE规范

    什么是J2EE? 在企业级应用中,都有一些通用企业需求模块,如数据库连接,邮件服务,事务处理等.既然很多企业级应用都需要这些模块,一些大公司便开发了自己的通用模块服务,即中间件.这样一来,就避免了重复 ...

  5. Html5 Canvas笔记(1)-CanvasAppTemplate代码

    学了一段时间的Html5 Canvas,现想一段一段的将学习笔记整理出来放上来,先整理一段Canvas的模版文件代码,以后建立Canvas程序就不用重新写这些代码了,当然最好是将这个Html代码保存到 ...

  6. Android常用adb命令

    1.进入手机命令行模式 adb shell 有多部手机的话 adb -s + 手机编号 + shell 2.安装apk adb install 然后将apk文件拖进命令行 卸载apk adb unin ...

  7. SIM9001GSM模块教程

    博主最近在做一个项目,用到了GSM模块,博主不是什么单片机大神,只是感觉某宝附带的资料太水,所以上传一些自己写的程序和经验,供需要的人参考 1,拨打电话 /********************** ...

  8. python作业设计:多级菜单,并可依次进入各级子菜单

    '''作业三:多级菜单 三级菜单 可依次选择进入各子菜单 所需新知识点:列表.字典 ''' data = { "北京":{ "昌平":{ "沙河&qu ...

  9. Latex 公式在线可视化编辑器

    寻觅 最近的一个demo需要用到Latex公式在线编辑器,从搜索引擎一般会得到类似http://latex.codecogs.com/eqneditor/editor.php的结果,这个编辑器的问题在 ...

  10. Linux--谈父子进程执行过程

    fork函数用于从已存在进程中创建一个新进程,新进程成为子进程,原进程成为父进程.这两个进程分别返回他们各自的返回值, 其中父进程的返回值是子进程的进程号,子进程则返回0,因此返回值大于0标识父进程, ...