從 JDBC 到 Mybatis,看這篇就夠了

2020-12-12 CSDN

作者 | 田維常 責編 | 張文

頭圖 | CSDN 下載自東方 IC

來源 | Java後端技術全棧(ID:jjs-2018)

本文思維導圖:

傳統 JDBC

1.1 傳統 JDBC 編碼格式

public class DataBaseUtil { public static final String URL = "jdbc:mysql://localhost:3306/mblog"; public static final String USER = "root"; public static final String PASSWORD = "123456";
public static void main(String[] args) throws Exception { Class.forName("com.mysql.jdbc.Driver"); //2. Connection conn = DriverManager.getConnection(URL, USER, PASSWORD); //3. Statement stmt = conn.createStatement; //4. ResultSet rs = stmt.executeQuery("SELECT id, name, age FROM m_user where id =1"); //如果有數據,rs.next返回true while(rs.next){ System.out.println("name: "+rs.getString("name")+" 年齡:"+rs.getInt("age")); } }}

上面代碼中知識為了展示 JDBC 整個過程(異常和資源是簡單粗暴的處理了,我們關注的點不在這兩個)。

大致可以分為六個步驟:

  1. 加載驅動程序;

  2. 獲得資料庫連接;

  3. 創建一個Statement對象;

  4. 操作資料庫,實現增刪改查;

  5. 獲取結果集;

  6. 關閉資源。

使用層面來說,採用原生態的 JDBC 在項目中使用起來成本還是很高的。如果我們的項目中的業務相對比較複雜,資料庫表也相對較多,各種操作資料庫的增刪改查的方法也會隨之多起來,那麼這樣的代碼重複次數會非常之多。

1.2 傳統 JDBC 的問題

  1. 創建資料庫的連接存在大量的硬編碼;

  2. 執行 statement 時存在硬編碼;

  3. 頻繁的開啟和關閉資料庫連接,會嚴重影響資料庫的性能,浪費資料庫的資源;

  4. 存在大量的重複性編碼。

為了解決以上問題,就誕生了各種各樣替換 JDBC 的產品。即 ORM 框架。

什麼是 ORM?

全稱為 Object Relational Mapping。對象-映射-關係型資料庫。對象關係映射(簡稱ORM、O/RM 或 O/R mapping),用於實現面向對象程式語言裡不同類型系統的數據之間的轉換。簡單的說,ORM 是通過使用描述對象和資料庫之間映射的元數據,將程序中的對象與關係資料庫相互映射。

ORM 提供了實現持久化層的另一種模式,它採用映射元數據來描述對象關係的映射,使得 ORM 中間件能在任何一個應用的業務邏輯層和資料庫層之間充當橋梁。

我們的項目中是這樣的:

比如:Apache DbUtils、Spring JDBC、 Hibernate、Ibatis(Mybatis 的前生)、Spring Data Jpa 等等。

目前最為流行的是 Mybatis 和 Spring Data Jpa。本系列我們先講解Mybatis,Jpa 後面再講。

ORM 的優缺點

優點:

  1. 提高了開發效率。由於 ORM 可以自動對 Entity 對象與資料庫中的 Table 進行欄位與屬性的映射,所以我們實際可能已經不需要一個專用的、龐大的數據訪問層。

  2. ORM 提供了對資料庫的映射,不用 sql 直接編碼,能夠像操作對象一樣從資料庫獲取數據。

缺點:犧牲程序的執行效率和會固定思維模式,降低了開發的靈活性。

從系統結構上來看,採用 ORM 的系統一般都是多層系統,系統的層次多了,效率就會降低。ORM 是一種完全的面向對象的做法,而面向對象的做法也會對性能產生一定的影響

在我們開發系統時,一般都有性能問題。性能問題主要產生在算法不正確和與資料庫不正確的使用上。ORM 所生成的代碼一般不太可能寫出很高效的算法,在資料庫應用上更有可能會被誤用,主要體現在對持久對象的提取和和數據的加工處理上,如果用上了 ORM,程式設計師很有可能將全部的數據提取到內存對象中,然後再進行過濾和加工處理,這樣就容易產生性能問題。

在對對象做持久化時 ORM 一般會持久化所有的屬性。有時,這是不希望的。但 ORM 是一種工具,工具確實能解決一些重複,簡單的勞動。這是不可否認的。我們不能指望工具能一勞永逸的解決所有問題,有些問題還是需要特殊處理的,但需要特殊處理的部分對絕大多數的系統,應該是很少的。

MyBatis

4.1 MyBatis 是什麼?

如果在面試的時候被問到,只要你說出下面三種即可。(來自官網)

  1. MyBatis 是一款優秀的持久層框架,它支持自定義 SQL、存儲過程以及高級映射。

  2. MyBatis 免除了幾乎所有的 JDBC 代碼以及設置參數和獲取結果集的工作。

  3. MyBatis 可以通過簡單的 XML 或註解來配置和映射原始類型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 對象)為資料庫中的記錄。

4.2 MyBatis 的優點和缺點

優點:

  1. 基於 SQL 語句編程,相當靈活,不會對應用程式或者資料庫的現有設計造成任何影響。SQL 寫在 XML 裡,解除 sql 與程序代碼的耦合,便於統一管理;提供 XML 標籤,支持編寫動態 SQL 語句,並可重用;

  2. 與 JDBC 相比,減少了 50% 以上的代碼量,消除了 JDBC 大量冗餘的代碼,不需要手動開關連接;

  3. 很好的與各種資料庫兼容(因為 MyBatis 使用 JDBC 來連接資料庫,所以只要 JDBC 支持的資料庫 MyBatis 都支持);

  4. 能夠與 Spring 很好的集成;

  5. 提供映射標籤,支持對象與資料庫的 ORM 欄位關係映射,提供對象關係映射標籤,支持對象關係組件維護。

缺點

  1. SQL 語句的編寫工作量較大。尤其當欄位多、關聯表多時,對開發人員編寫 SQL 語句的功底有一定要求。

  2. SQL 語句依賴於資料庫,導致資料庫移植性差,不能隨意更換資料庫。

Mybatis環境搭建及簡單實例

5.1 創建一張資料庫表

創建一張 m_user 表使用 MySQL 資料庫。

CREATE TABLE `m_user` ( `id` int(11) NOT AUTO_INCREMENT, `name` varchar(255) DEFAULT , `age` int(11) DEFAULT , PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

添加依賴

<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> <scope>runtime</scope> </dependency></dependencies>

項目結構如下:

創建一個 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> <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/mblog?useUnicode=true"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/UserMapper.xml"/> </mappers></configuration>

實體類User

ublic class User { private Integer id; private String name; private Integer age; //set get @Override public String toString { return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; }}

創建 UserMapper.java

import com.tian.mybatis.entity.User;
public interface UserMapper { User selectUserById(Integer id);}

創建 UserMapper.xml

<?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="com.tian.mybatis.mapper.UserMapper"> <select id="selectUserById" resultType="com.tian.mybatis.entity.User"> select * from m_user where id = #{id} </select></mapper>

創建一個測試類

import com.tian.mybatis.entity.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 java.io.IOException;import java.io.InputStream;
public class MybatisApplication {
public static void main(String[] args) { String resource = "mybatis-config.xml"; InputStream inputStream = ; SqlSession sqlSession =; try { inputStream = Resources.getResourceAsStream(resource); //工廠模式 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder.build(inputStream); //sql操作會話 sqlSession = sqlSessionFactory.openSession; //獲取數據並解析成User對象 User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectUserById", 1); System.out.println(user); } catch (Exception e) { e.printStackTrace; }finally { try { inputStream.close; } catch (IOException e) { e.printStackTrace; } sqlSession.close; } }
}

輸出結果:

User{id=1, name='tian', age=22}

整體步驟:

另外一種啟動方式:

import com.tian.mybatis.entity.User;import org.apache.ibatis.builder.xml.XMLConfigBuilder;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.Configuration;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
import java.io.IOException;import java.io.InputStream;import java.util.Properties;
public class MybatisApplication {
public static void main(String[] args) { String resource = "mybatis-config.xml"; InputStream inputStream = ; try { inputStream = Resources.getResourceAsStream(resource); } catch (IOException e) { e.printStackTrace; } //解析xml文件 XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, , ); //構建一個SqlSessionFactory工廠類 SqlSessionFactory sqlSessionFactory = build(parser.parse); //創建一個SqlSession SqlSession sqlSession = sqlSessionFactory.openSession; //獲取數據並解析成User對象 User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectUserById", 1); System.out.println(user); }
public static SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }}

輸出和上面一樣。還可以直接使用 Java 代碼而不用 mybatis-config.xml。

//創建數據源DataSource dataSource = getDataSource;
TransactionFactory transactionFactory = new JdbcTransactionFactory;
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder.build(configuration);

小總結:

從上面這個案例中我們大致能猜到,

Mybatis 中最主要幾個組件:SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper。

SqlSessionFactoryBuilder 這個類可以被初始、使用和丟棄,如果你已經創建好了一個 SqlSessionFactory 後就不用再保留它。

因此 ,SqlSessionFactoryBuilder 的最好作用域是方法體內,比如說定義一個方法變量。

你可以重複使用 SqlSessionFactoryBuilder 生成多個 SqlSessionFactory 實例,但是最好不要強行保留,因為 XML 的解析資源要用來做其它更重要的事。

SqlSessionFactory 一旦創建,SqlSessionFactory 就會在整個應用過程中始終存在。所以沒有理由去銷毀和再創建它,一個應用運行中也不建議多次創建 SqlSessionFactory。如果真的那樣做,會顯得很拙劣。

因此 SqlSessionFactory 最好的作用域是 Application。可以有多種方法實現。

最簡單的方法是單例模式或者是靜態單例模式。然而這既不是廣泛贊成和好用的。反而,使用 Google Guice 或 Spring 來進行依賴反射會更好。這些框架允 許你生成管理器來管理 SqlSessionFactory 的單例生命周期

SqlSession 每個線程都有自己的 SqlSession 實例,SqlSession 實例是不能被共享,也是不是線程安全的。因此最好使用 Request 作用域或者方法體作用域。

不要使用類的靜態變量來引用一個 SqlSession 實例,甚至不要使用類的一個實例變更來引用。永遠不要在一個被管理域中引用 SqlSession。比如說在 Servlet 中的HttpSession 中。如果你正在使用 WEB 框架,應該讓 SqlSession 跟隨 HTTP 請求的相似作用域。

也就是說,在收到一個 HTTP 請求過後,打開 SqlSession,等返回一個回應以後,立馬關掉這個 SqlSession。關閉 SqlSession 是非常重要的。你必須要確保 SqlSession 在 finally 方法體中正常關閉。

SqlSession session = sqlSessionFactory.openSession;try {// do work} finally {session.close;}

使用這種模式來貫穿你的所有代碼,以確保所有資料庫資源都被完全關閉。

Mapper:

Mapper 是一種你創建的用於綁定映射語句的接口。Mapper 接口的實例是用 SqlSession 來獲得的。同樣,從技術上來說,最廣泛的 Mapper 實例作用域像 SqlSession 一樣,使用請求作用域。確切地說,

在方法被調用的時候調用 Mapper 實例,然後使用後,就自動銷毀掉。

不需要使用明確的註銷。當一個請求執行正確無誤的時候,像 SqlSession 一樣,你可以輕而易舉地操控這一切。保持簡單性,保持 Mapper 在 方法體作用域內。

//獲取數據並解析成User對象 User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectUserById", 1); System.out.println(user);

這裡映射涉及到四個主體:

  1. 實體類 User;

  2. 接口 UaerMapper;

  3. xml 配置文件 UserMapper;

  4. 資料庫表 m_user。

Mybatis 的五部曲:

總結

本文主要回顧 JDBC 的 demo、JDBC 中的問題、創建一個 Mybatis 示例、總結出重要的四個組件以及每個組件的作用,希望對大家有所幫助。

點分享

相關焦點

  • 武漢課工場Pyhton培訓:SpringBoot集成Mybatis這一篇就夠了
    武漢課工場Pyhton培訓:SpringBoot集成Mybatis這一篇就夠了!如果大家用過Mybatis的話應該會發現,Mybatis依賴的artifactId是mybatis-spring-boot-starter,而接下來我們要講的SpringDataJPA依賴的artifactId卻是spring-boot-starter-data-jpa,從這個名字關鍵字(mybatis、jpa)的順序上,我們就能看出來誰才是親生的。
  • MyBatis的SQL執行流程不清楚?看完這一篇就夠了
    ,其他的我們先不看,我們直接看最後解析mappers節點5、繼續進入PreparedStatementHandler對象的query方法,可以看到,這一步就是調用了jdbc操作對象PreparedStatement中的execute方法,最後一步就是轉換結果集然後返回。
  • SpringBoot集成mybatis-plus
    這篇文章介紹SpringBoot集成Mybatis-Plus,同時介紹使用easyCode通過指定的資料庫表生成對應的bean、mapper.xml、mapper.java、service.java、serviceImpl.java和controller。
  • 詳解mybatis和Mybatis-Plus區別
    於是有下面的↓Mybatis Generator:自動為Mybatis生成簡單的增刪改查sql語句的工具,省去一大票時間,兩者配合使用,開發速度快到飛起。注意:mybatis-plus的核心jar包中已集成了mybatis和mybatis-spring,所以為避免衝突,請勿再次引用這兩個jar包。.......
  • springboot整合mybatis
    本篇文章來手把手帶進行springboot與mybatis的整合,springboot的版本我選擇的是2.2.2.RELEASE,mybatis的是選擇mybatis-spring-boot-starter的一個組件,資料庫我選擇的是mysql,為了方便,我這裡省略了service層,也及是業務處理層
  • MyBatis怎麼連接到Mysql資料庫?
    昨天講解了如何給配置文件導入約束,今天完成配置之後就可以連接到Mysql資料庫,首先說一下SqlMapConfig.xml中標籤的作用。大家看一下,environments 是它的環境標籤,在這個標籤裡面有一個transactionManager標籤:這是指定一個事物管理器。
  • 從零開始手寫 mybatis (三)jdbc pool 從零實現資料庫連接池
    前景回顧第一節 從零開始手寫 mybatis(一)MVP 版本 中我們實現了一個最基本的可以運行的 mybatis。第二節 從零開始手寫 mybatis(二)mybatis interceptor 插件機制詳解本節我們一起來看一下如何實現一個資料庫連接池。為什麼需要連接池?資料庫連接的創建是非常耗時的一個操作,在高並發的場景,如果每次對於資料庫的訪問都重新創建的話,成本太高。
  • MyBatis初級實戰之六:一對多關聯查詢
    準備數據本次實戰,在名為mybatis的資料庫中建立兩個表(和前面幾篇文章中的表結構一模一樣):user和log表;user;action" column="log_action" jdbcType="VARCHAR" /> <result property="createTime" column="log_create_time" jdbcType="TIMESTAMP" />
  • mybatis從入門到精通,第一篇《入門基本搭建》,乾貨滿滿
    --引入mybatis依賴--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.6</version> </dependency&
  • MyBatis框架學習
    目錄總結jdbc出現的問題mybatis介紹mybatis入門程序&34;jdbc:mysql://127.0.0.1:3306/liwei&34;root&34;root&34;select * from user where id = ?
  • SpringBoot整合MyBatis+詳細列印執行SQL語句
    圖片來源網路為啥寫這篇文章呢,有人可能會說springBoot的mybatis的starter都有了寫這篇文章不是多此一舉嗎其實我一開始也是使用mybatis的starter的,但是當我需要配置一個讓mybatis可以將執行sql語句列印出來的配置時,難到了我,所以才想和大家分享一下springBoot整合MyBatis的方法,如果大家有更好地方法,歡迎討論。
  • mybatis源碼環境的搭建
    下載源碼mybatis源碼地址:https://github.com/mybatis/mybatis-3,直接打開地址然後在點擊右側Release找到想要的版本,下載源碼Source Code到本地就行了,這裡我下載的zip。
  • Spring boot整合mybatis多數據源簡單使用
    但是,如果涉及一些數據遷移等應用,可能會涉及將數據從一個庫遷移到另外一個庫,甚至是不同類型的資料庫,比如MySQL到Oracle。這篇博文,我們不介紹mybatis的基本使用,只介紹基於mybatis配置多數據源的方法。
  • Spring集成MyBatis | Spring系列第53篇
    1、本文內容【文末送書】本文主要介紹mybatis和spring集成的兩種方式,對MyBatis不熟悉的,建議先看一下MyBatis高手系列目前註解的方式我們用的比較多,所以主要介紹註解的方式,xml的方式這裡就暫時不介紹了。
  • Mybatis-plus常用API全套教程,看完沒有不懂的
    INSERT INTO user (id, name, age, email) VALUES(1, &39;, 18, &39;),(2, &39;, 20, &39;),(3, &39;, 28, &39;),(4, &39;, 21, &39;),(5, &39;, 24, &39;);注意:-- 真實開發中往往都會有這四個欄位
  • MyBatis入門案例——親測可用
    mybatis/mybatis --><dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId>
  • mybatis環境搭建
    在 properties 文件中定義屬性名要有一定的特殊性,如: XXXXX.XXXXX.XXXX的形式,就像 jdbc.driver 。這樣可以防止和 parameterType 傳遞的屬性名衝突,從而被覆蓋掉。2、 settingsmybatis 全局配置參數,全局參數將會影響 mybatis 的運行行為。比如:開啟二級緩存、開啟延遲加載。
  • Mybatis中類型映射處理器詳解
    我們都知道mybatis只是一個ORM框架,並不是針對具體的資料庫,需要兼容多種資料庫,所以mybatis可以根據不同的資料庫廠商執行不同的語句,這種多廠商的支持是基於映射語句中的 databaseId 屬性。
  • SpringBoot:資料庫訪問之Mybatis
    在SpringBoot中使用mybatis非常簡單,我們只需要引入依賴即可。</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version></dependency><dependency> <groupId>mysql</groupId>
  • 一、Mybatis基本應用
    持久層框架:專注於解決數據持久化的框架(mybatis、hibernate、spring jdbc)表現層框架:專注於解決與用戶交互的框架(struts2、spring mvc)全棧框架: 能在各層都給出解決方案的框架(spring)SSM =  spring+ springmvc + mybatis(學習這個框架)二、Mybatis簡介原始jdbc