小白手把手教學用spring框架實現mybatis和mysql以及工作原理

ivanlee717發表於2024-10-31

Maven_Mybatis_Mysql

什麼是Mybatis

MyBatis 是一款優秀的持久層框架,它支援自定義 SQL、儲存過程以及高階對映。MyBatis 免除了幾乎所有的 JDBC 程式碼以及設定引數和獲取結果集的工作。MyBatis 可以透過簡單的 XML 或註解來配置和對映原始型別、介面和 Java POJO(Plain Old Java Objects,普通老式 Java 物件)為資料庫中的記錄。

簡單來說,MyBatis是一個開源的持久層框架,它提供了一種簡單且強大的方式來與關係型資料庫進行互動。MyBatis透過使用XML或註解來定義資料庫操作,並透過原生的SQL查詢語句與資料庫進行互動。

持久化

持久化是將程式資料在持久狀態和瞬時狀態間轉換的機制。

  • 即把資料(如記憶體中的物件)儲存到可永久儲存的儲存裝置中(如磁碟)。持久化的主要應用是將記憶體中的物件儲存在資料庫中,或者儲存在磁碟檔案中、XML資料檔案中等等。
  • JDBC就是一種持久化機制。檔案IO也是一種持久化機制。
  • 在生活中 : 將鮮肉冷藏,吃的時候再解凍的方法也是。將水果做成罐頭的方法也是。

為什麼需要持久化服務呢?那是由於記憶體本身的缺陷引起的

  • 記憶體斷電後資料會丟失,但有一些物件是無論如何都不能丟失的,比如銀行賬號等,遺憾的是,人們還無法保證記憶體永不掉電。
  • 記憶體過於昂貴,與硬碟、光碟等外存相比,記憶體的價格要高2~3個數量級,而且維持成本也高,至少需要一直供電吧。所以即使物件不需要永久儲存,也會因為記憶體的容量限制不能一直呆在記憶體中,需要持久化來快取到外存。

為什麼需要Mybatis?

  • Mybatis就是幫助程式猿將資料存入資料庫中 , 和從資料庫中取資料 .

  • 傳統的jdbc操作 , 有很多重複程式碼塊 .比如 : 資料取出時的封裝 , 資料庫的建立連線等等… , 透過框架可以減少重複程式碼,提高開發效率 .

  • MyBatis 是一個半自動化的ORM框架 (Object Relationship Mapping) —>物件關係對映

  • 所有的事情,不用Mybatis依舊可以做到,只是用了它,所有實現會更加簡單!技術沒有高低之分,只有使用這個技術的人有高低之別

  • MyBatis的優點

    • 簡單易學:本身就很小且簡單。沒有任何第三方依賴,最簡單安裝只要兩個jar檔案+配置幾個sql對映檔案就可以了,易於學習,易於使用,透過文件和原始碼,可以比較完全的掌握它的設計思路和實現。
    • 靈活:mybatis不會對應用程式或者資料庫的現有設計強加任何影響。sql寫在xml裡,便於統一管理和最佳化。透過sql語句可以滿足運算元據庫的所有需求。
    • 解除sql與程式程式碼的耦合:透過提供DAO層,將業務邏輯和資料訪問邏輯分離,使系統的設計更清晰,更易維護,更易單元測試。sql和程式碼的分離,提高了可維護性。
    • 提供xml標籤,支援編寫動態sql。

工作原理

我們知道,JDBC有四個核心物件:
(1)DriverManager,用於註冊資料庫連線
(2)Connection,與資料庫連線物件
(3)Statement/PrepareStatement,運算元據庫SQL語句的物件
(4)ResultSet,結果集或一張虛擬表

而MyBatis也有四大核心物件:
(1)SqlSession物件,該物件中包含了執行SQL語句的所有方法。類似於JDBC裡面的Connection 。
(2)Executor介面,它將根據SqlSession傳遞的引數動態地生成需要執行的SQL語句,同時負責查詢快取的維護。類似於JDBC裡面的Statement/PrepareStatement。
(3)MappedStatement物件,該物件是對對映SQL的封裝,用於儲存要對映的SQL語句的id、引數等資訊。
(4)ResultHandler物件,用於對返回的結果進行處理,最終得到自己想要的資料格式或型別。可以自定義返回型別

在JDBC中,Connection不直接執行SQL方法,而是利用Statement或者PrepareStatement來執行方法。在使用JDBC建立了連線之後,可以使用Connection介面的createStatement()方法來獲取Statement物件,也可以呼叫prepareStatement()方法獲得PrepareStatement物件,透過executeUpdate()方法來執行SQL語句。而在MyBatis中,SqlSession物件包含了執行SQL語句的所有方法,但是它是委託Executor執行的。從某種意義上來看,MyBatis裡面的SqlSession類似於JDBC中的Connection,他們都是委託給其他類去執行。

image-20241030173317584

  1. 從配置檔案中讀取資訊,mybatis-config.xml為MyBatis的全域性配置檔案,用於配置資料庫連線資訊。

    <?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>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC"/>
                    <property name="username" value="root"/>
                    <property name="password" value="xxxxx"/>
                </dataSource>
            </environment>
        </environments>
        <mappers>
            <mapper resource="Mapper/UserMapper.xml"/>
        </mappers>
    </configuration>
    
  2. 載入對映檔案。對映檔案即SQL對映檔案,該檔案中配置了運算元據庫的SQL語句,需要在MyBatis配置檔案mybatis-config.xml中載入。mybatis-config.xml 檔案可以載入多個對映檔案,每個檔案對應資料庫中的一張表。

    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.ivanlee.pojo.User">
        <select id="findById" parameterType="int" resultType="com.ivanlee.pojo.User">
            select * from users where uid = #{id}
        </select>
    </mapper>
    
  3. 構造會話工廠。透過MyBatis的環境配置資訊構建會話工廠SqlSessionFactory。SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);

  4. 建立會話物件。由會話工廠建立SqlSession物件,該物件中包含了執行SQL語句的所有方法。SqlSession session = sqlMapper.openSession();

  5. Executor執行器。MyBatis底層定義了一個Executor介面來運算元據庫,它將根據SqlSession傳遞的引數動態地生成需要執行的SQL語句,同時負責查詢快取的維護。

  6. MappedStatement物件。在Executor介面的執行方法中有一個MappedStatement型別的引數,該引數是對對映資訊的封裝,用於儲存要對映的SQL語句的id、引數等資訊。

  7. 輸入引數對映。輸入引數型別可以是Map、List等集合型別,也可以是基本資料型別和POJO型別。輸入引數對映過程類似於JDBC對preparedStatement物件設定引數的過程。

  8. 輸出結果對映。輸出結果型別可以是Map、List等集合型別,也可以是基本資料型別和POJO型別。輸出結果對映過程類似於JDBC對結果集的解析過程。

POJO

POJO是“Plain Old Java Object”的縮寫,直譯為“簡單老式Java物件”。這個術語最早出現在Java社群中,用以描述那些沒有遵循特定設計模式、沒有繼承特定類、也沒有實現特定介面的普通Java物件。簡而言之,POJO類就是最基礎的Java類,也可以理解為普通的Java類。例如如下程式碼:

public class User {
    private int uid;
    private String uname;
    private int uage;
    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public int getUage() {
        return uage;
    }
    public void setUage(int uage) {
        this.uage = uage;
    }
}

在與資料庫互動時,POJO類可以作為持久化物件,將資料庫中的表對映為Java物件,方便程式設計師進行資料庫操作。為什麼說POJO的設計更能簡化開發?其實本質上就是我們在開發中先定義核心的POJO,比如上面的User類,它與我們的業務相關,它是關於使用者資料承載的類,但我們只是簡單的基於物件導向設計理念,將使用者抽象為一個User類,它具有使用者相關的屬性描述,此時基於物件導向OO、基本的Java語言規範以及基本的開發規範(屬性private、對外getter、setter)就完成了一個基本的POJO。其他人一看,它就是一個純粹的Java物件罷了,它有基本的屬性和方法。

程式碼樣例

image-20241031110933721

這是整個的程式碼結構,根據前面講到的mybatis配置設定這種目錄結構,會比較清晰。首先我們先建一個資料庫,然後用idea連線上。

image-20241030113434304

image-20241030113534231

image-20241030113922690

連線好以後就可以寫一下資料庫的配置檔案,db.properties

mysql.driver=com.mysql.cj.jdbc.Driver
mysql.username=root
mysql.password=xxxxx
mysql.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false
package com.ivanlee.test;
import com.ivanlee.pojo.User;
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.junit.Test;
import java.io.Reader;
import java.io.IOException;

public class UserTest {
    @Test
    public void userFindByTest() {
        String resources = "mybatis-config.xml";
        Reader reader = null;
        try {
            reader = Resources.getResourceAsReader(resources);
        }catch (IOException e) {
            e.printStackTrace();
        }
        SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = sqlMapper.openSession();
        User user = session.selectOne("findById",1);
        System.out.println("姓名\t年齡");
        System.out.println(user.getUname()+"\t"+user.getUage());
        session.close();
    }
}

新建一個user類用來進行測試,"findById" 是一個 SQL 語句的識別符號,它通常定義在一個 MyBatis 的對映檔案(XML 檔案或註解方式)中。這個識別符號對應於一個具體的 SQL 查詢語句,用於從資料庫中查詢資料。1 是傳遞給 SQL 語句的引數,表示你要查詢的記錄的主鍵值。image-20241031112712516

這裡的findById是我們在mapper對映裡定義好的方法,不是java庫定義的

如果想列印更多的資訊,我們還可以繼續新增搜尋方式,寫到mapper裡面。image-20241031114828054

List<User> users = session.selectList("findAll");
System.out.println("姓名\t年齡");
for(User user: users){
    System.out.println(user.getUname()+"\t"+user.getUage());
}

image-20241031114858280

相關文章