一起學MyBatis之入門篇(2)

来源:https://www.cnblogs.com/hsiang/archive/2019/12/21/12078570.html
-Advertisement-
Play Games

本文主要講解MyBatis中類型轉換的功能,其實在MyBatis中,提供了預設的數據類型之間的轉換,但只是基本數據類型的轉換,如果跨類型進行轉換,則需要自定義轉換類,如java中是boolean類型,在資料庫中則是int類型,則需要進行java類型到jdbc類型的轉換。本文僅供學習分享使用,如有不足... ...


概述

本文主要講解MyBatis中類型轉換的功能,其實在MyBatis中,提供了預設的數據類型之間的轉換,但只是基本數據類型的轉換,如果跨類型進行轉換,則需要自定義轉換類,如java中是boolean類型,在資料庫中則是int類型,則需要進行java類型到jdbc類型的轉換,僅供學習分享使用,如有不足之處,還請指正。

轉換方法

實現類型轉換有兩種方法,本文主要採用第2種方法。如下所示:

  1. 實現TypeHandler 介面,但是比較麻煩。
  2. 繼承BaseTypeHandler<T>基類,實現抽象方法,其中T表示待轉換類型,即Java中的源類型。

應用場景

說明:

  1. 有一個Student類,屬性stuSex性別是Boolean類型,true表示男,false表示女,
  2. 在資料庫中有一個Student表,stuSex欄位,是int類型,1表示男,0表示女,
  3. 則需要在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,有以下幾點,需要註意:

  1. 如果是 簡單類型(8個基本類型+String):
    • 可以採用#{id}方式,其中id可以任意值,且會自動進行類型轉換,給String類型加上單引號,可以防止SQL註入。
    • 可以採用${value}的方式寫,必須是value,不可以寫其他,且原樣輸出,不會給String加上單引號,不可以防止SQL註入。
  2. 如果是複雜類型,則需要寫屬性名,兩者都一樣

級聯屬性

假如學生有兩個屬性: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 }
29     
View 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>

備註

日出未必意味著光明,太陽也無非是一顆晨星;只有在我們醒著時,才是真正的破曉 !!!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本書內容 本書從書名就可以看出來,講了架構的兩個東西,一個是原理,一個是案例。 案例部分沒有在導圖中體現,不過建議讀者還是要看一下案例,能夠通過案例對原理有更加深刻的印象 推薦程度 4.5 顆星 推薦原因 通讀本書,能對大型網站有更加直觀的感受 細節之處,能夠指導你設計網站架構選用的具體方案 即使以 ...
  • 運算符 目標 算數運算符 比較(關係)運算符 邏輯運算符 賦值運算符 運算符的優先順序 數學符號錶鏈接: "https://zh.wikipedia.org/wiki/數學符號表" 01. 算數運算符 是完成基本的算術運算使用的符號,用來處理四則運算 | 運算符 | 描述 | 實例 | | : : | ...
  • 判斷(if)語句 目標 開發中的應用場景 if 語句體驗 if 語句進階 綜合應用 01. 開發中的應用場景 生活中的判斷幾乎是無所不在的,我們每天都在做各種各樣的選擇,如果這樣?如果那樣?…… 程式中的判斷 判斷的定義 如果 條件滿足 ,才能做某件事情, 如果 條件不滿足 ,就做另外一件事情,或者 ...
  • 變數的命名 目標 標識符和關鍵字 變數的命名規則 0.1 標識符和關鍵字 1.1 標識符 標示符就是程式員定義的 變數名 、 函數名 名字 需要有 見名知義 的效果,見下圖: 標示符可以由 字母 、 下劃線 和 數字 組成 不能以數字開頭 不能與關鍵字重名 思考:下麵的標示符哪些是正確的,哪些不正確 ...
  • 變數的基本使用 程式就是用來處理數據的,而變數就是用來存儲數據的 目標 變數定義 變數的類型 變數的命名 01. 變數定義 在 Python 中,每個變數 在使用前都必須賦值 ,變數 賦值以後 該變數 才會被創建 等號(=)用來給變數賦值 左邊是一個變數名 右邊是存儲在變數中的值 變數定義之後,後續 ...
  • 一、處理異常的第二種方法 1.try......catch... 語法: try{ 可能出現異常的代碼; }catch{ 處理異常的代碼; }catch{ 註意: (1)引入了什麼異常,catch裡面就要寫清楚,出現了什麼異常該怎麼辦; (2)異常也可以有父類和子類,按照從上到下的順序進行捕捉;因此 ...
  • 整體架構 我們想要瞭解一個框架,首先要瞭解它是乾什麼的,Tomcat我們都知道,是用於處理連接過來的Socket請求的。那麼Tomcat就會有兩個功能: 對外處理連接,將收到的位元組流轉化為自己想要的Request和Response對象 對內處理Servlet,將對應的Request請求分發到相應的S ...
  • 總結: 伺服器根據url找到類全名,通過反射Class.forName(servlet類全名)創建了servlet對象,伺服器將所有請求數據封裝到request對象中,所有響應數據封裝到response中,將request和response傳入service方法,是使用反射調用service方法。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...