本文主要講解MyBatis中類型轉換的功能,其實在MyBatis中,提供了預設的數據類型之間的轉換,但只是基本數據類型的轉換,如果跨類型進行轉換,則需要自定義轉換類,如java中是boolean類型,在資料庫中則是int類型,則需要進行java類型到jdbc類型的轉換。本文僅供學習分享使用,如有不足... ...
概述
本文主要講解MyBatis中類型轉換的功能,其實在MyBatis中,提供了預設的數據類型之間的轉換,但只是基本數據類型的轉換,如果跨類型進行轉換,則需要自定義轉換類,如java中是boolean類型,在資料庫中則是int類型,則需要進行java類型到jdbc類型的轉換,僅供學習分享使用,如有不足之處,還請指正。
轉換方法
實現類型轉換有兩種方法,本文主要採用第2種方法。如下所示:
- 實現TypeHandler 介面,但是比較麻煩。
- 繼承BaseTypeHandler<T>基類,實現抽象方法,其中T表示待轉換類型,即Java中的源類型。
應用場景
說明:
- 有一個Student類,屬性stuSex性別是Boolean類型,true表示男,false表示女,
- 在資料庫中有一個Student表,stuSex欄位,是int類型,1表示男,0表示女,
- 則需要在java類型和jdbcType之間進行轉換,才能正確顯示。
類型轉換實現步驟
1.新增BooleanAndIntConverter轉換類,該類繼承BaseTypeHandler<Boolean>基類,如下所示:
需要實現的抽象方法有4個【1個set方法(java-->jdbcType的轉換),3個get方法(jdbcType-->java的轉換)】,
1 package com.hex.converter; 2 3 import java.sql.CallableStatement; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 8 import org.apache.ibatis.type.BaseTypeHandler; 9 import org.apache.ibatis.type.JdbcType; 10 11 /** 12 * 類型轉換器(java-jdbc之間的類型轉換) 13 * 方法:1.實現介面TypeHandler 14 * 2.或者繼承基類 15 * @author Administrator 16 * Boolean:表示待轉換類型,即源類型 17 */ 18 public class BooleanAndIntConverter extends BaseTypeHandler<Boolean> { 19 20 /** 21 * 結果是可空的返回內容 22 * rs:結果集 23 * columeName:列名 24 */ 25 @Override 26 public Boolean getNullableResult(ResultSet rs, String columeName) throws SQLException { 27 int num=rs.getInt(columeName); 28 return num==1?true:false; 29 } 30 31 /*** 32 * 結果是可空的返回內容 33 * rs:結果集 34 * colomeIndex:列索引 35 */ 36 @Override 37 public Boolean getNullableResult(ResultSet rs, int columeIndex) throws SQLException { 38 int num=rs.getInt(columeIndex); 39 return num==1?true:false; 40 } 41 42 /** 43 * 結果是可空的返回內容 44 * cs:存儲過程方式 45 */ 46 @Override 47 public Boolean getNullableResult(CallableStatement cs, int columeIndex) throws SQLException { 48 int num=cs.getInt(columeIndex); 49 return num==1?true:false; 50 } 51 52 /** 53 * set表示 java--jdbc類型 54 * ps:表示預編譯的sql對象 55 * i:表示修改的位置索引 56 * parameter:表示參數的java類型 57 * arg3:表示數據的類型 58 */ 59 @Override 60 public void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType arg3) throws SQLException { 61 // 如是true,則資料庫類型為1,否則數據類型為false 62 if(parameter){ 63 ps.setInt(i, 1); 64 }else{ 65 ps.setInt(i, 0); 66 } 67 } 68 }
2. 在MyBatis的配置文件中,聲明類型轉換,和environments平級,如下所示:
jdbcType="INTEGER"是枚舉類型,必須大寫。
1 <typeHandlers> 2 <typeHandler handler="com.hex.converter.BooleanAndIntConverter" javaType="Boolean" jdbcType="INTEGER" /> 3 </typeHandlers>
3.定義一個Student類,該類有一個stuSex屬性,是boolean類型
1 /** 2 * 性別 3 */ 4 private boolean stuSex; 5 6 public boolean isStuSex() { 7 return stuSex; 8 } 9 public void setStuSex(boolean stuSex) { 10 this.stuSex = stuSex; 11 }
4.查詢時,需要在Mapper文件中進行配置類型轉換,如下所示:
1 <resultMap type="Student" id="studentResult"> 2 <id property="stuId" column="stuId"/> 3 <result property="stuName" column="stuName"/> 4 <result property="stuAge" column="stuAge"/> 5 <!-- 此處需要類型轉換,需要說明一下:jdbcType的值必須大寫,是枚舉類型 --> 6 <result property="stuSex" column="stuSex" javaType="boolean" jdbcType="INTEGER"/> 7 </resultMap> 8 <select id="queryStudentById" resultMap="studentResult" parameterType="int"> 9 select * from Student where stuId = #{id} 10 </select>
註意:
如果jdbc類型和java的類型完全一致,則使用resultType,否則用resultMap
如果java中的欄位名稱和java中的欄位名稱一致,則用resultType,否則用resultMap
5. 增加StudentMapper介面,採用動態代理的方式進行調用
1 package com.hex.mybatis; 2 3 import java.util.List; 4 5 public interface StudentMapper { 6 /** 7 * 通過ID查詢:動態代理 1. 函數名稱和Mapper標簽ID一致 2. 參數類型和parameterType對應的一致 3. 8 * 返回值和resultType一致 9 * 10 * @param pid 11 * @return 12 */ 13 Student queryStudentById(int pid); 14 15 /** 16 * 新增 17 * 18 * @param student 19 */ 20 void addStudent(Student student); 21 22 23 /** 24 * 通過地址查詢學生 25 * @param student 26 * @return 27 */ 28 List<Student> queryStudentByAddress(Student student); 29 30 }
6. 對於新增,則需要在語句中進行類型轉換,如下所示:
如果需要類型轉換,則需要如下寫法:#{stuSex,javaType=boolean,jdbcType=INTEGER},進行boolean和INTEGER類型的轉換
1 <insert id="addStudent" parameterType="Student" > 2 insert into Student(stuId,stuName,stuAge,stuSex)values(#{stuId},#{stuName},#{stuAge},#{stuSex,javaType=boolean,jdbcType=INTEGER}) 3 </insert>
對於入參,即ParameterType,有以下幾點,需要註意:
- 如果是 簡單類型(8個基本類型+String):
- 可以採用#{id}方式,其中id可以任意值,且會自動進行類型轉換,給String類型加上單引號,可以防止SQL註入。
- 可以採用${value}的方式寫,必須是value,不可以寫其他,且原樣輸出,不會給String加上單引號,不可以防止SQL註入。
- 如果是複雜類型,則需要寫屬性名,兩者都一樣
級聯屬性
假如學生有兩個屬性:homeAddress(家庭地址),schoolAddress(學校地址),有一個Address地址類,包含這兩個屬性,如下所示:
1 public class Address { 2 3 /** 4 * 家庭住址 5 */ 6 private String homeAddress; 7 /** 8 * 學校住址 9 */ 10 private String schoolAddress; 11 12 public String getHomeAddress() { 13 return homeAddress; 14 } 15 public void setHomeAddress(String homeAddress) { 16 this.homeAddress = homeAddress; 17 } 18 public String getSchoolAddress() { 19 return schoolAddress; 20 } 21 public void setSchoolAddress(String schoolAddress) { 22 this.schoolAddress = schoolAddress; 23 } 24 }
而Student類中有一個地址屬性,如下所示:
1 /** 2 * 地址 3 */ 4 private Address address; 5 6 public Address getAddress() { 7 return address; 8 } 9 10 public void setAddress(Address address) { 11 this.address = address; 12 }
以下進行模糊查詢,在Mapper文件中配置,如下所示:
1 <select id="queryStudentByAddress" resultMap="studentResult" parameterType="int"> 2 select * from Student where homeAddress like '%${address.homeAddress}%' and schoolAddress like '%${address.schoolAddress}%' 3 </select>
此處採用${address.homeAddress}進行模糊查詢,而不是#{xxxx}的方式,方便拼接。
採用動態代理的方式測試代碼如下:
1 public static void main(String[] args) throws IOException { 2 //以輸入流的方式載入配置文件 3 String resource = "mybatis-config.xml"; 4 InputStream inputStream = Resources.getResourceAsStream(resource); 5 //創建SqlSessionFactory對象,build第二個參數指定environment的id,,如果不寫,預設配置default. 6 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 7 //創建會話對象 8 SqlSession session = sqlSessionFactory.openSession(); 9 10 StudentMapper mapper=session.getMapper(StudentMapper.class); 11 // Student student = mapper.queryStudentById(2); 12 // System.out.println(student); 13 // System.out.println("查詢成功"); 14 // Student student2=new Student(2,"lili",true,20); 15 // mapper.addStudent(student2); 16 // session.commit(); 17 // System.out.println("新增成功"); 18 //關閉會話對象 19 Student student =new Student(); 20 Address address=new Address("S","S"); 21 student.setAddress(address); 22 List<Student> lstStudents = mapper.queryStudentByAddress(student); 23 for(Student s : lstStudents){ 24 System.out.println(s); 25 } 26 System.out.println("查詢成功"); 27 session.close(); 28 } 29View Code
配置別名
因為本類中會頻繁用到,所示配置了別名,方便使用,如下所示:
1 <!-- 設置別名,忽略大小寫,當一個類頻繁用到時,則可以定義別名 --> 2 <typeAliases> 3 <!-- 每一個類,定義一個別名 --> 4 <!-- <typeAlias type="com.hex.mybatis.Product" alias="product" /> --> 5 6 <!-- 以下批量定義別名,所有包裡面的類名,就是別名 --> 7 <package name="com.hex.mybatis"/> 8 <!-- 除了自定義別名,MyBatis還內置了需要別名 --> 9 </typeAliases>
備註
日出未必意味著光明,太陽也無非是一顆晨星;只有在我們醒著時,才是真正的破曉 !!!