MyBatis入門與實例

框架

框架(Framework)是整個或部分系統的可重用設計,表現爲一組抽象構件及構件實例間交互的方法;另一種定義認爲,框架是可被應用開發者定製的應用骨架。可以說,一個框架是一個可複用的設計構件,它規定了應用的體系結構,闡明瞭整個設計、協作構件之間的依賴關係、責任分配和控制流程,表現爲一組抽象類以及其實例之間協作的方法,它爲構件複用提供上下文(Context)關係。——百度百科

對於程序員來說,框架是一套資源,這套資源中會包含 Jar 包、文檔,還有些會包含源碼、代碼示例等。這套資源從相關的官網上可以下載。一般是以壓縮文件的形式出現。

Mybatis 概述

MyBatis 本是 apache 的一個開源項目 iBatis, 2010 年這個項目由 apache 遷移到了 google,並更名爲 MyBatis。 2013 年遷移到 Github。——百度百科《MyBatis》

Mybatis 簡介

MyBatis 是一個優秀的基於 Java 的持久層框架,它內部封裝了 JDBC,使開發者只需關注 SQL 語句本身,而不用再花費精力去處理諸如註冊驅動、創建 Connection、 配置 Statement
等繁雜過程。

Mybatis 通過 xml 或註解的方式將要執行的各種 statement (statement、preparedStatement 等)配置起來,並通過 Java 對象和 Statement 中 SQL 的動態參數進行映射生成最終執行的 SQL 語句,最後由 MyBatis 框架執行 SQL 並將結果映射成 Java 對象並返回。

Mybatis 與 Hibernate

Hibernate 框架是提供了全面的數據庫封裝機制的“全自動” ORM,即實現了 POJO 和數據庫表之間的映射,以及 SQL 的自動生成和執行。

相對於此, MyBatis 只能算作是“半自動” ORM。其着力點,是在 POJO 類 與 SQL 語句之間的映射關係。也就是說, MyBatis 並不會爲程序員自動生成 SQL 語句。具體的 SQL 需要程序員自己編寫,然後通過 SQL 語句映射文件,將 SQL 所需的參數,以及返回的結果字段映射到指定 POJO。因此, MyBatis 成爲了“全自動” ORM 的一種有益補充。

與 Hibernate 相比, MyBatis 具有以下幾個特點:

  • 在 XML 文件中配置 SQL 語句,實現了 SQL 語句與代碼的分離,給程序的維護帶來
    了很大便利。
  • 因爲需要程序員自己去編寫 SQL 語句,程序員可以結合數據庫自身的特點靈活控
    制 SQL 語句,因此能夠實現比 Hibernate 等全自動 ORM 框架更高的查詢效率,能夠完成復
    雜查詢。
  • 簡單,易於學習,易於使用,上手快。

Mybatis 體系結構

{% asset_img mybatis01.png %}

Mybatis 工作原理

{% asset_img mybatis02.jpg %}

第一個 Mybatis 程序

需求: 實現將 Student 信息寫入到 DB 中。

基本程序

1. 導入 Jar 包

除了需要導入 MyBatis 的核心 Jar 包及依賴 Jar 包外,還需要導入 MySQL 的驅動 Jar 包,JUnit 測試的 Jar 包。

在這裏插入圖片描述

2.定義實體類

package com.huang.beans;

public class Student {
	private Integer id;
	private String name;
	private int age;
	private double score;
	
	public Student(String name, int age, double score) {
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public double getScore() {
		return score;
	}
	public void setScore(double score) {
		this.score = score;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + ", score=" + score + "]";
	}
	

}

3. 在 DB 中生成表結構,即創建空表

{% asset_img mybatis03.jpg %}

注意:
由於後面要創建的 MyBatis 映射文件映射的是 SQL 語句,而非像 Hibernate 一樣,是類到表,屬性到字段的映射。所以, MyBatis 要求, 在創建數據庫表時,字段名要與屬性名一致,如果不一致,需要通過 resultMap 解決。

4. 定義 Dao 接口

package com.huang.dao;

import com.huang.beans.Student;

public interface IStudentDao {
	void insertStu(Student student);

}

5. 定義映射文件

映射文件,簡稱爲 mapper,主要完成 Dao 層中 SQL 語句的映射。映射文件名隨意,一般放在 dao 包中。 這裏映射文件名稱定爲 mapper.xml。

映射文件的約束文件常用有兩種:.dtd、.xsd,約束文件 mybatis-3-mapper.dtd 文件,在 MyBatis 的核心 Jar 包的 org.apache.ibatis.builder.xml 包中存放。當然,主配置文件的約束 dtd 文件也在該位置存放。

映射文件內容爲:

<?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="test">
	<insert id="insertStudent"
	parameterType="com.huang.beans.Student">
		insert into student(name,age,score) 
		values(#{name},#{age}, #{score})
	</insert>
</mapper>

注意:
#{ }中寫入的是 Student 類的屬性名。

6. 定義主配置文件

在主配置文件中添加約束,即配置文件頭,配置文件名也可以隨意命名,這裏命名爲 mybatis.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="onlineEM">
		<environment id="onlineEM">
			<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/test"/>
				<property name="username" value="root"/>
				<property name="password" value="123456"/>
			</dataSource>
		</environment>
		<environment id="testEM">
			<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/test"/>
				<property name="username" value="root"/>
				<property name="password" value="123456"/>
			</dataSource>
		</environment>
	</environments>
	
	<!-- 註冊映射文件 -->
	<mappers>
		<mapper resource="com/huang/dao/mapper.xml"/>
	</mappers>
	
</configuration>

7. 定義 Dao 實現類

package com.huang.dao;

import java.io.IOException;
import java.io.InputStream;

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 com.huang.beans.Student;

public class StudentDaoImpl implements IStudentDao {
	
	private SqlSession sqlSession;

	@Override
	public void insertStu(Student student) {
		try {
			//1.讀取主配置文件
			InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
			//2.創建SqlSessionFactory對象
			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
			//創建SqlSession對象
			sqlSession = sqlSessionFactory.openSession();
			//操作
			sqlSession.insert("insertStudent",student);
			//SqlSession提交
			sqlSession.commit();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//SqlSession關閉,添加了close()不用作事務回滾
			if (sqlSession != null) {
				sqlSession.close();
				
			}
		}
		
	}

}

8. 定義測試類

package com.huang.test;

import org.junit.Before;
import org.junit.Test;

import com.huang.beans.Student;
import com.huang.dao.StudentDaoImpl;

public class MyTest {
	private StudentDaoImpl dao;
	
	@Before
	public void before() {
		dao= new StudentDaoImpl();
	}
	@Test
	public void test01() {
		Student student = new Student("趙六", 26, 97.5);
		dao.insertStu(student);
	}

}

9. 添加日誌控制文件

MyBatis 使用 Log4j 進行日誌處理,而 Login4j2 對其支持並不好,所以在 MyBatis 中需要將 log4j.properties 放入到項目的 src 目錄下。

若將日誌級別設置爲 debug,則可以顯示出所執行的 SQL 語句、參數值、對 DB 的影響條數等信息。若將級別設置爲 trace,則還可顯示出查詢出的每條記錄的每個字段名及值。

在這裏插入圖片描述

注意:
若日誌對象使用根日誌對象 rootLogger,則會輸出太多的信息。在 MyBatis 中,可以指定要輸出日誌的工作空間 namespace 的名字。此時,只會輸出該 namespace 下執行的 SQL 的日誌內容。

##define a logger
log4j.logger.test=debug,console

10. 運行結果

{% asset_img mybatis04.jpg %}

使用工具類

由於每一次執行 SqlSession 的方法,均需首先獲取到該對象。而 SqlSession 對象的獲取又相對比較繁瑣,所以,可以將獲取 SqlSession 對象定義爲一個工具類方法。

SqlSession 對象是通過 SqlSessionFactory 對象創建的。由於 SqlSessionFactory 類爲重量級對象,且爲線程安全的,所以可以將 SqlSessionFactory 對象定義爲單例的。

1. 創建工具類

package com.huang.dao;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyBatisUtil {
	private static SqlSessionFactory factory;
	public static SqlSession getSqlSession() {
		try {
			
			if (factory == null) {
				//讀取主配置文件
				InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
				//創建SqlSession工廠
				factory = new SqlSessionFactoryBuilder().build(inputStream);
				
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return factory.openSession();
	}

}

2. 修改 Dao 接口的實現類

package com.huang.dao;

import org.apache.ibatis.session.SqlSession;

import com.huang.beans.Student;

public class StudentDaoImpl implements IStudentDao {
	
	private SqlSession sqlSession;

	@Override
	public void insertStu(Student student) {
		try {
			sqlSession = MyBatisUtil.getSqlSession();
			//操作
			sqlSession.insert("insertStudent",student);
			//SqlSession提交
			sqlSession.commit();
		} finally {
			//SqlSession關閉,添加了close()不用作事務回滾
			if (sqlSession != null) 
				sqlSession.close();
			
		}
		
	}

}

從屬性文件中讀取 DB 連接四要素

爲了方便對數據庫連接的管理, DB 連接四要素數據一般都是存放在一個專門的屬性文件中的。 MyBatis 主配置文件需要從這個屬性文件中讀取這些數據。

1. 定義屬性文件

在 src 下定義屬性文件 jdbc.properties。

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.user=root
jdbc.password=123456

2. 修改主配置文件

對主配置文件,第一,需要註冊屬性文件。第二,需要從屬性文件中通過 key,將其 value 讀取出來。

<!-- 註冊屬性文件 -->
    <properties resource="jdbc.properties"/>

主配置文件詳解

主配置文件名可以隨意命名,其主要完成以下幾個功能:
(1)註冊存放 DB 連接四要素的屬性文件;
(2)註冊實體類的全限定性類名的別名;
(3)配置 MyBatis 運行環境,即數據源與事務管理器;
(4)註冊映射文件。

註冊 DB 連接四要素屬性文件

<!-- 註冊DB連接四要素屬性文件 -->
	<properties resource="jdbc.properties"/>

指定實體類全限定性類名的別名

對於實體類的全限定性類名的別名指定方式,一般使用方式。這樣做的好處是會將該包中所有實體類的簡單類名指定爲別名,寫法簡單方便。

<!-- 定義類型別名 -->
	<typeAliases>
		<!-- 將指定包中所有類的簡單類名當作其別名 -->
		<package name="com.huang.beans"/>
	</typeAliases>

不過,還有另外的指定方式:通過指定。

<typeAliases>
	    <typeAlias type="com.huang.beans.Student" alias="Student"/>
	</typeAliases>
  • type:全限定性類名
  • alias:別名

該方式的好處是,可以指定別名爲簡單類名以外的其它名稱。當然,弊端是,必須逐個指定,比較繁瑣。

另外,Mybatis 還提供了內置的類型別名:

基本類型:

別名 類型 別名 類型
int int integer int
_short short _long long
_double double _float float
byte byte boolean boolean

常用包類型別名:

別名 類型 別名 類型
string String byte Byte
long Long short Short
int Integer integer Integer
double Double float Float
boolean Boolean date Date
object Object collection Collection
list List arraylist ArrayList
map Map hashmap HashMap
iterator Iterator

配置 MyBatis 的運行環境

配置 MyBatis 的運行環境,主要是配置數據源與事務管理器。

1. <environments/>標籤

<!-- 指定默認運行環境 -->
	<environments default="onlineEM">
	<!-- 項目上線環境 -->
		<environment id="onlineEM">
		</environment>
		
		<!-- 項目測試環境 -->
		<environment id="testEM">
		</environment>
	</environments>

在 <environments/> 中可包含多個運行環境 <environment/>,但其 default 屬性指定了當前 MyBatis 運行時所選擇使用的環境。<environment/> 的 id 屬性爲當前定義的運行環境的名稱,可以任意命名。該名稱會作爲 <environments/> 的 default 屬性的值出現。

2. <transactionManager/> 標籤

<!-- 使用jdbc事務管理 -->
<transactionManager type="JDBC"/>

該標籤用於指定 MyBatis 所使用的事務管理器。 MyBatis 支持兩種事務管理器類型: JDBC 與 MANAGED。

  • JDBC:使用 JDBC 的事務管理機制。即,通過 Connection 的 commit()方法提交,通過 rollback() 方法回滾。但默認情況下, MyBatis 將自動提交功能關閉了,改爲了手動提交。即程序中需要顯式的對事務進行提交或回滾。從日誌的輸出信息中可以看到。
  • MANAGED:由容器來管理事務的整個生命週期(如 Spring 容器)。
  1. <dataSource/> 標籤
    該標籤用於配置 MyBatis 使用的數據源類型與數據庫連接基本屬性。常見有類型有: UNPOOLED、 POOLED、 JDNI 等。
  • UNPOOLED :不使用連接池。即每次請求,都會爲其創建一個 DB 連接,使用完畢後,會馬上將此連接關閉。
  • POOLED:使用數據庫連接池來維護連接。
  • JNDI:數據源可以定義到應用的外部,通過 JNDI 容器獲取數據庫連接。
<!-- 數據庫連接池 -->
<dataSource type="POOLED">
	<property name="driver" value="com.mysql.jdbc.Driver"/>
	<property name="url" value="jdbc:mysql://localhost:3306/test"/>
	<property name="username" value="root"/>
	<property name="password" value="123456"/>
</dataSource>

若要從屬性文件中讀取 DB 連接四要素信息,則使用如下方式:

			
<!-- 數據庫連接池 -->
<dataSource type="POOLED">
	<property name="driver" value="${jdbc.driverClassName}"/>
	<property name="url" value="${jdbc.url}"/>
	<property name="username" value="${jdbc.user}"/>
	<property name="password" value="${jdbc.password}"/>
</dataSource>

指定映射文件

指定映射文件的方式有多種。但所有的方式,都是指定在 <mappers/> 標籤中的。

<mapper resource=””/> 指定映射文件

若映射文件只有一個,則可直接使用如下形式:

<!-- 註冊映射文件 -->
	<mappers>
		<mapper resource="com/huang/dao/mapper.xml"/>
	</mappers>

若映射文件有多個,則可使用如下形式:

<!-- 註冊映射文件 -->
	<mappers>
		<mapper resource="com/huang/dao/mapper.xml"/>
		<mapper resource="com/huang/dao/mapper2.xml"/>
	</mappers>

API 詳解

Dao 中需要通過 SqlSession 對象來操作 DB。而 SqlSession 對象的建,需要其工廠對象 SqlSessionFactory。 SqlSessionFactory 對象,需要通過其構建器對象 SqlSessionFactoryBuilder 的 build()方法,在加載了主配置文件的輸入流對象後創建。

Resources 類

Resources 類,顧名思義就是資源,用於讀取資源文件。其有很多方法通過加載並解析資源文件,返回不同類型的 IO 流對象。

SqlSessionFactoryBuilder 類

SqlSessionFactory 的創建,需要使用 SqlSessionFactoryBuilder 對象的 build() 方法。由於 SqlSessionFactoryBuilder 對象在創建完工廠對象後,就完成了其歷史使命,即可被銷燬。所以,一般會將該 SqlSessionFactoryBuilder 對象創建爲一個方法內的局部對象,方法結束,對象銷燬。

SqlSessionFactory 接口

SqlSessionFactory 接口對象是一個重量級對象(系統開銷大的對象),是線程安全的, 所以一個應用只需要一個該對象即可。 創建 SqlSession 需要使用 SqlSessionFactory 接口的的 openSession() 方法。

  • openSession(true):創建一個有自動提交功能的 SqlSession
  • openSession(false):創建一個非自動提交功能的 SqlSession,需手動提交
  • openSession():同 openSession(false)

SqlSession 接口

SqlSession 接口對象用於執行持久化操作。一個 SqlSession 對應着一次數據庫會話,一次會話以 SqlSession 對象的創建開始,以 SqlSession 對象的關閉結束。

SqlSession 接口對象是線程不安全的,所以每次數據庫會話結束前,需要馬上調用其 close() 方法,將其關閉。再次需要會話,再次創建。 而在關閉時會判斷當前的 SqlSession 是否被提交:若沒有被提交,則會執行回滾後關閉;若已被提交,則直接將 SqlSession 關閉。所以, SqlSession 無需手工回滾。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章