在大學寫web應用的時候常常會遇到這麼個問題,當我要插入一條數據,某個數據是Date類型,數據庫中倒是VARCHAR類型,這個時候可能會傻乎乎的先把這個數據本身手動轉換成String類型再插入到數據庫中,其實大可沒必要。MyBatis爲咱們提供了更好的方法便是TypeHandler來應對Java和jdbc字段類型不匹配的狀況。MyBatis中內置了很多的TypeHandler,若是咱們想要本身自定義一個TypeHandler能夠實現TypeHandler接口,也能夠繼承BaseTypeHandler類。下面咱們實現一個將Java中的Date類型利用咱們自定義的ExampleTypeHandler來轉換爲JDBC的VARCHAR類型。java
咱們對MyBatis的介紹先侷限在使用,在會使用事後咱們再究其原理、源碼。mysql
1 package day_8_mybatis.util; 2 3 import java.sql.CallableStatement; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 import java.util.Date; 8 9 import org.apache.ibatis.type.BaseTypeHandler; 10 import org.apache.ibatis.type.JdbcType; 11 12 /** 13 * 注意在引入Date所在的包時,是java.util.Date,而不是java.sql.Date,這一點不要搞錯。 14 * @author turbo 15 * 16 * 2016年10月23日 17 */ 18 public class ExampleTypeHandler extends BaseTypeHandler<Date> { 19 20 /* 根據列名,獲取能夠爲空的結果 21 * @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.ResultSet, java.lang.String) 22 */ 23 @Override 24 public Date getNullableResult(ResultSet rs, String columnName) 25 throws SQLException { 26 String sqlTimetamp = rs.getString(columnName); 27 if (null != sqlTimetamp){ 28 return new Date(Long.valueOf(sqlTimetamp)); 29 } 30 return null; 31 } 32 33 /* 根據列索引,獲取能夠爲空的結果 34 * @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.ResultSet, int) 35 */ 36 @Override 37 public Date getNullableResult(ResultSet rs, int columnIndex) 38 throws SQLException { 39 String sqlTimetamp = rs.getString(columnIndex); 40 if (null != sqlTimetamp){ 41 return new Date(Long.valueOf(sqlTimetamp)); 42 } 43 return null; 44 } 45 46 /*47 * @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.CallableStatement, int) 48 */ 49 @Override 50 public Date getNullableResult(CallableStatement cs, int columnIndex) 51 throws SQLException { 52 String sqlTimetamp = cs.getString(columnIndex); 53 if (null != sqlTimetamp){ 54 return new Date(Long.valueOf(sqlTimetamp)); 55 } 56 return null; 57 } 58 59 /* 設置非空參數 60 * @see org.apache.ibatis.type.BaseTypeHandler#setNonNullParameter(java.sql.PreparedStatement, int, java.lang.Object, org.apache.ibatis.type.JdbcType) 61 */ 62 @Override 63 public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, 64 JdbcType jdbcType) throws SQLException { 65 ps.setString(i, String.valueOf(parameter.getTime())); 66 } 67 68 69 70 }
咱們已經自定義了一個TypeHandler,接着咱們要在mybatis-config.xml中註冊。程序員
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 6 <configuration> 7 <!-- 注意configuration中各個屬性配置的順序應爲:properties,settings,typeAliases,typeHandlers,objectFactory,objectWrapperFactory,reflectorFactory,plugins,environments,databaseIdProvider,mappers)--> 8 <properties> 9 <property name="driver" value="com.mysql.jdbc.Driver"/> 10 <property name="url" value="jdbc:mysql://localhost:3306/test"/> 11 <property name="username" value="root"/> 12 <property name="password" value="0000"/> 13 </properties> 14 <typeHandlers> 15 <typeHandler handler="day_8_mybatis.util.ExampleTypeHandler" javaType="java.util.Date" jdbcType="VARCHAR"/> 16 </typeHandlers> 17 18 <environments default="development"> 19 <environment id="development"> 20 <transactionManager type="JDBC" /> 21 <dataSource type="POOLED"> 22 <property name="driver" value="${driver}"/> 23 <property name="url" value="${url}"/> 24 <property name="username" value="${username}"/> 25 <property name="password" value="${password}"/> 26 </dataSource> 27 </environment> 28 </environments> 29 <mappers> 30 <mapper resource="day_8_mybatis/mapper/UserMapper.xml"/> 31 <mapper resource="day_8_mybatis/mapper/NoteMapper.xml"/> 32 </mappers> 33 34 </configuration> 35 36
注意各個屬性配置有順序之分,不能隨意穿插。web
準備工做已經作完了,咱們接着循序漸進的實現POJO類 Note裏面包含id和date字段。sql
1 package day_8_mybatis.pojo; 2 3 import java.util.Date; 4 5 /** 6 * @author turbo 7 * 8 * 2016年10月23日 9 */ 10 public class Note { 11 private int id; 12 private Date date; 13 public int getId() { 14 return id; 15 } 16 public void setId(int id) { 17 this.id = id; 18 } 19 public Date getDate() { 20 return date; 21 } 22 public void setDate(Date date) { 23 this.date = date; 24 } 25 }
接着是負責與數據庫交互Dao層的NoteMapper接口,咱們只舉例查詢和插入。數據庫
1 package day_8_mybatis.mapper; 2 3 import day_8_mybatis.pojo.Note; 4 5 /** 6 * @author turbo 7 * 8 * 2016年10月23日 9 */ 10 public interface NoteMapper { 11 Note queryNote(int id); 12 void insertNote(Note note); 13 }
咱們再來看看在NoteMapper.xml中是如何利用咱們剛纔自定義的TypeHandler。apache
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="day_8_mybatis.mapper.NoteMapper"> 6 <resultMap type="day_8_mybatis.pojo.Note" id="note-base"> 7 <result property="id" column="id"/> 8 <result property="date" column="date" typeHandler="day_8_mybatis.util.ExampleTypeHandler"/> 9 </resultMap> 10 11 <select id="queryNote" parameterType="int" resultMap="note-base"> 12 select * from note where id = #{id} 13 </select> 14 <insert id="insertNote" parameterType="day_8_mybatis.pojo.Note"> 15 insert into note (id, date) values(#{id}, #{date, typeHandler=day_8_mybatis.util.ExampleTypeHandler}) <!--使用咱們自定義的TypeHandler--> 16 </insert> 17 </mapper>
最後咱們在客戶端測試一下。session
1 package day_8_mybatis; 2 3 import java.io.IOException; 4 import java.util.Date; 5 6 import org.apache.ibatis.session.SqlSession; 7 8 import day_8_mybatis.mapper.NoteMapper; 9 import day_8_mybatis.pojo.Note; 10 import day_8_mybatis.util.SessionFactory; 11 12 /** 13 * 客戶端 14 * @author turbo 15 * 16 * 2016年9月11日 17 */ 18 public class Main { 19 20 /** 21 * @param args 22 * @throws IOException 23 */ 24 public static void main(String[] args) throws Exception { 25 String resource = "day_8_mybatis/mybatis-config.xml"; //獲取mybatis配置文件路徑 26 SqlSession sqlSession = SessionFactory.getSqlSession(resource); //經過SessionFactory工具類(此工具類爲本身構造即util包中的SessionFactory)構造SqlSession 27 28 NoteMapper noteMapper = sqlSession.getMapper(NoteMapper.class); 29 30 Note note = new Note(); 31 note.setId(1); 32 note.setDate(new Date()); 33 noteMapper.insertNote(note); //插入 34 sqlSession.commit(); //注意須要手動提交事務 35 36 note = noteMapper.queryNote(2); //查詢 37 System.out.println(note.getDate()); 38 } 39 40 }
注意在34行代碼,須要手動提交事務,默認是關閉自動提交的,因此必須手動提交。開始沒有提交事務,不管怎麼都沒辦法插入到數據庫,後來debug單步調試的時候發現了autoCommit=false,纔想起來在之前大學的時候也遇到過這個這個問題因此一下就定位問題在哪兒了。mybatis
數據庫中只有一個note表,字段爲id類型爲int,date字段爲varchar。app
至此咱們就完成了自定義的TypeHandler,其實MyBatis爲咱們提供的TypeHandler已經很多了,不過咱們仍是本身試驗一把,先把MyBatis學會使用,再究其原理。
這是一個能給程序員加buff的公衆號