Mybatis筆記(一)


目錄

MyBatis

MyBatis簡介

MyBatis作用

  • MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優秀的持久層框架。
  • MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。
  • MyBatis可以使用簡單的XML用於配置和原始映射,將接口和Java的POJO類映射成數據庫中的記錄
  • 使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如注冊驅動、創建connection、創建statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。

歷史

  • 原是apache的一個開源項目iBatis
  • 2010年6月這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis 。
  • iBATIS一詞來源於“internet”和“abatis”的組合,是一個基於Java的持久層框架。

為什么要使用MyBatis?

JDBC

  • SQL夾在Java代碼塊里,耦合度高導致硬編碼內傷
  • 維護不易且實際開發需求中sql是有變化,頻繁修改的情況多見
  • 要自已創建connection、創建statement、手動設置參數、結果集檢索等

Hibernate

  • 長難復雜SQL,對於Hibernate而言處理也不容易
  • 內部自動生產的SQL,不容易做特殊優化。
  • 基於全映射的全自動框架,javaBean存在大量字段時無法只映射部分字段。導致數據庫性能下降。

Mybatis

  • 對開發人員而言,核心sql還是需要自己優化
  • MyBatis是一個半自動化的持久化層框架。
  • MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優秀的持久層框架。

MyBatis入門程序

1.下載Mybatis核心包

http://www.mybatis.org/mybatis-3/getting-started.html
https://github.com/mybatis/mybatis-3/releases

2.創建工程,引入MyBatis核心包及依賴包

ant-1.9.6.jar
ant-launcher-1.9.6.jar
asm-5.2.jar
cglib-3.2.5.jar
commons-logging-1.2.jar
javassist-3.22.0-GA.jar
junit-4.9.jar
log4j-1.2.17.jar
log4j-api-2.3.jar
log4j-core-2.3.jar
lombok.jar
mybatis-3.4.6.jar
mysql-connector-java-5.1.7-bin.jar
ognl-3.1.16.jar
slf4j-api-1.7.25.jar
slf4j-log4j12-1.7.25.jar

3.創建customer表,建立與表對象的domain

package com.le.domain;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Setter@Getter@ToString
public class Customer {
    private Integer cust_id;
    private String cust_name;
    private String cust_profession;
    private String cust_phone;
    private String email;
}

4.創建MyBatis核心配置文件SqlMappingConfig.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>
    <!-- spring整合后 environments配置將廢除 使用spring中的連接池 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事務管理 -->
            <transactionManager type="JDBC" />
            <!-- 數據庫連接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url"
                          value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="1234" />
            </dataSource>
        </environment>
    </environments>
</configuration>
	<!DOCTYPE configuration
			PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
			"http://mybatis.org/dtd/mybatis-3-config.dtd">
	<configuration>
		<!-- spring整合后 environments配置將廢除 使用spring中的連接池 -->
		<environments default="development">
			<environment id="development">
				<!-- 使用jdbc事務管理 -->
				<transactionManager type="JDBC" />
				<!-- 數據庫連接池 -->
				<dataSource type="POOLED">
					<property name="driver" value="com.mysql.jdbc.Driver" />
					<property name="url"
							  value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
					<property name="username" value="root" />
					<property name="password" value="1234" />
				</dataSource>
			</environment>
		</environments>
	</configuration>

5.創建與表對象的關系映射Mapping文件編寫sql語句

<?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="myTest">
    <!--根據cust_id查詢客戶-->
    <select id="queryCustomerById" parameterType="Int" resultType="com.le.domain.Customer">
	  SELECT * FROM `customer` WHERE cust_id  = #{cust_id}
	</select>
</mapper>

6.在SqlMappingConfig.xml核心配置文件當中引入Mapping

<!--加載映射文件-->
<mappers>
      <mapper resource="com/le/domain/Customer.xml"></mapper>
</mappers>

7.創建工廠,執行sql語句

@Test
public void test() throws IOException {
   /* //1.sqlSessionFactoryBuilder 加載配置文件
	SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
	
	//2.讀取配置文件
	InputStream resourceAsStream = Resources.getResourceAsStream("SqlMappingConfig.xml");
	
	//3.獲取session工廠
	SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
	
	//4.獲取會話   ---JDBC 連接
	SqlSession sqlSession = sessionFactory.openSession();*/
	SqlSession sqlSession = MybatisUtils.openSession();
	
	//5.執行sql
	Customer customer = sqlSession.selectOne("queryCustomerById", 2);
	System.out.println(customer);
	
	//6.關閉session
	sqlSession.close();
}

MyBatis核心Api

SqlSessionFactoryBuilder

  • SqlSessionFactoryBuilder用於創建SqlSessionFacoty
  • SqlSessionFacoty一旦創建完成就不需要SqlSessionFactoryBuilder了
  • 因為SqlSession是通過SqlSessionFactory創建的
  • 所以可以將SqlSessionFactoryBuilder當成一個工具類使用,最佳使用范圍是方法范圍即方法體內局部變量。

SqlSessionFactory

  • 創建sqlSession的工廠,是一個接口
  • 接口中定義了openSession的不同重載方法
  • SqlSessionFactory的最佳使用范圍是整個應用運行期間,一旦創建后可以重復使用,通常以單例模式管理SqlSessionFactory。

SqlSession

  • 連接到數據庫的一個會話
  • sqlSession中定義了數據庫操作方法。
  • 每個線程都應該有它自己的SqlSession實例
  • SqlSession的實例不能共享使用,它也是線程不安全的。因此最佳的范圍是請求或方法范圍
  • 絕對不能將SqlSession實例的引用放在一個類的靜態字段或實例字段中。

MyBatis架構

MyBatis-查詢

MybatisUtils工具類

package com.le.utils;

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 MybatisUtils {
    public static final  SqlSessionFactory sessionFactory;
    static {
        //1.sqlSessionFactoryBuilder 加載配置文件
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //2.讀取配置文件
        InputStream resourceAsStream = null;
        try {
            resourceAsStream = Resources.getResourceAsStream("SqlMappingConfig.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //3.獲取session工廠
        sessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
    }

    public static SqlSession openSession(){
        return sessionFactory.openSession();
    }
}

查詢所有客戶

<!--查詢所有-->
<select id="queryAllCustomer" resultType="com.le.domain.Customer">
   SELECT * FROM `customer`
</select>
@Test
public void test2() {
	SqlSession sqlSession = MybatisUtils.openSession();
	/*查詢所有的用戶*/
	List<Customer> queryAllCustomer = sqlSession.selectList("queryAllCustomer");
	for (Customer customer : queryAllCustomer) {
		System.out.println(customer);
	}
	sqlSession.close();
}

根據用戶名模糊查詢客戶

方式1

<!--根據用戶名模糊查詢客戶-->
<select id="querytCustomerByName" parameterType="String" resultType="com.le.domain.Customer">
	select * from customer where cust_name like '%{value}%';
</select>

@Test
public void test3(){
	SqlSession sqlSession = MybatisUtils.openSession();
	List<Customer> customers = sqlSession.selectList("querytCustomerByName", "%李%");
	for (Customer customer : customers) {
		System.out.println(customer);
	}
	sqlSession.close();
}


方式2

<!--根據用戶名模糊查詢客戶-->
<select id="querytCustomerByName" parameterType="String" resultType="com.le.domain.Customer">
	select * from customer where cust_name like #{name};
</select>		

總結

parameterType
	指定輸入參數類型
	mybatis通過ognl從輸入對象中獲取參數值拼接在sql中
resultType
	指定輸出結果類型
	mybatis將sql查詢結果的一行記錄數據映射為resultType指定類型的對象。如果有多條數據,則分別進行映射,並把對象放到容器List中
selectOne
	查詢一條記錄
	如果使用selectOne查詢多條記錄則拋出異常
selectList
	可以查詢一條或多條記錄
#{}和${}
	#{}
		表示一個占位符號,通過#{}可以實現preparedStatement向占位符中設置值
		自動進行java類型和jdbc類型轉換
		#{}可以有效防止sql注入
		#{}可以接收簡單類型值或pojo屬性值
		如果parameterType傳輸單個簡單類型值,#{}括號中可以是value或其它名稱
	${}
		表示拼接sql串
		通過${}可以將parameterType 傳入的內容拼接在sql中且不進行jdbc類型轉換
		${}可以接收簡單類型值或pojo屬性值
		如果parameterType傳輸單個簡單類型值,${}括號中只能是value

保存更新刪除

添加客戶,返回添加過后自增的主鍵

<!--添加-->
<insert id="insertCustom" parameterType="com.le.domain.Customer">
	/*獲取插入的最后一個id*/
	<selectKey keyColumn="cust_id" keyProperty="cust_id" resultType="Integer" order="AFTER">
		select last_insert_id()
	</selectKey>

	insert into `customer`(cust_name,cust_profession,cust_phone,email)
	values (#{cust_name},#{cust_profession},#{cust_phone},#{email})
</insert>	
/*添加客戶*/
@Test
public void insert(){
    SqlSession sqlSession = MybatisUtils.openSession();
    Customer customer = new Customer();
    customer.setCust_name("后裔2");
    customer.setCust_phone("18907897879");
    sqlSession.insert("insertCustom",customer);
    //當要改動數據庫當中的記錄時,執行sql時要自己提交事務
    //手動提交事務
    sqlSession.commit();
    System.out.println(customer.getCust_id());
    sqlSession.close();
}

更新客戶

<!--更新-->
<update id="updateCustomer" parameterType="com.le.domain.Customer">
	update `customer` set cust_name=#{cust_name} where cust_id=#{cust_id}
</update>

/*更新操作*/
@Test
public void update(){
    SqlSession sqlSession = MybatisUtils.openSession();
    Customer customer = sqlSession.selectOne("queryCustomerById", 12);
    customer.setCust_name("孫悟空");
    sqlSession.update("updateCustomer",customer);
    sqlSession.commit();
    sqlSession.close();
}


刪除客戶

<!--刪除操作-->
<delete id="deleteCustomer" parameterType="com.le.domain.Customer">
	delete from `customer` where cust_id=#{cust_id}
</delete>	

/*刪除*/
@Test
public void delete(){
    SqlSession sqlSession = MybatisUtils.openSession();
    Customer customer = sqlSession.selectOne("queryCustomerById", 12);
    sqlSession.delete("deleteCustomer",customer);
    sqlSession.commit();
    sqlSession.close();
}

MyBatis開發DAO

原始Dao開發方法

package com.le.dao;

import com.le.domain.Customer;
import java.util.List;

public interface CustomerDao {
    public Customer getCustomerWithId(Integer id);
    public List<Customer> getAllCustomer();
    public void addCustomer(Customer customer);
    public void  updateCustomer(Customer customer);
}

package com.le.dao;

import com.le.domain.Customer;
import com.le.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

public class CustomerDaoImpl implements CustomerDao {
    @Override
    public Customer getCustomerWithId(Integer id) {
        SqlSession sqlSession = MybatisUtils.openSession();
        Customer customer = sqlSession.selectOne("queryCustomerById", id);
        return customer;
    }

    @Override
    public List<Customer> getAllCustomer() {
        SqlSession sqlSession = MybatisUtils.openSession();
        List<Customer> customers = sqlSession.selectList("queryAllCustomer");
        return customers;
    }

    @Override
    public void addCustomer(Customer customer) {
        SqlSession sqlSession = MybatisUtils.openSession();
        sqlSession.insert("insertCustom",customer);
    }

    @Override
    public void updateCustomer(Customer customer) {
        SqlSession sqlSession = MybatisUtils.openSession();
        sqlSession.update("insertCustom",customer);
    }
}

@Test
public void test() throws IOException {
    //1.sqlSessionFactoryBuilder 加載配置文件
    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    //2.讀取配置文件
    InputStream resourceAsStream = Resources.getResourceAsStream("SqlMappingConfig.xml");
    //3.獲取session工廠
    SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
    //4.獲取會話   ---JDBC 連接
    SqlSession sqlSession = sessionFactory.openSession();

    //5.執行sql
    Customer customer = sqlSession.selectOne("queryCustomerById", 2);
    System.out.println(customer);
    //6.關閉session
    sqlSession.close();
}


Mapper動態代理

要求

  • namespace必須和Mapper接口類路徑一致
  • id必須和Mapper接口方法名一致
  • parameterType必須和接口方法參數類型一致
  • resultType必須和接口方法返回值類型一致

過程

package com.le.mapper;

import com.le.domain.Customer;
import java.util.List;

public interface CustomerMapper {
    //根據cust_id查詢客戶
    public Customer queryCustomerById(Integer id);
}	
<?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.le.mapper.CustomerMapper">
    <!--根據cust_id查詢客戶-->
    <select id="queryCustomerById" parameterType="Integer"
            resultType="com.le.domain.Customer">
	  SELECT * FROM `customer` WHERE cust_id  = #{cust_id}
	</select>
</mapper>		
@Test
public void test(){
 SqlSession sqlSession = MybatisUtils.openSession();
        CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
        Customer customer = mapper.queryCustomerById(1);
        System.out.println(customer);
        sqlSession.close();
}

selectOne和selectList

  • 動態代理對象調用sqlSession.selectOne()和sqlSession.selectList()是根據mapper接口方法的返回值決定
  • 如果返回list則調用selectList方法,如果返回單個對象則調用selectOne方法。

參數傳遞

單個參數

  • 可以接受基本類型,對象類型,集合類型的值。
  • MyBatis可直接使用這個參數,不需要經過任何處理。

多個參數

  • 任意多個參數,都會被MyBatis重新包裝成一個Map傳入。
  • Map的key是param1,param2…,值就是參數的值。

​ 示例

@Test
public void test3(){
    SqlSession sqlSession = MybatisUtils.openSession();
    CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
	Customer customer = mapper.queryCustomerById(1,"魯班大師");
    System.out.println(customer);
    sqlSession.close();
}

<!--根據cust_id 和 cust_name查詢客戶-->
<select id="queryCustomerById"
		resultType="com.le.domain.Customer">
  SELECT * FROM `customer` WHERE cust_id  = #{arg0} and cust_name=#{arg1}
</select>


@param命名參數

  • 為參數使用@Param起一個名字,
  • MyBatis就會將這些參數封裝進map中,key就是我們自己指定的名字

​ 示例

public interface CustomerMapper {
    /*
    * 根據cust_id查詢客戶
    * */
    public Customer queryCustomerById(@Param("cust_id") Integer id,@Param("cust_name") String cust_name);
}
<!--根據cust_id 和 cust_name查詢客戶-->
<select id="queryCustomerById"
		resultType="com.le.domain.Customer">
  SELECT * FROM `customer` WHERE cust_id  = #{arg0} and cust_name=#{arg1}
</select>

@Test
public void test(){
    SqlSession sqlSession = MybatisUtils.openSession();
    CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
	Customer customer = mapper.queryCustomerById(1,"魯班大師");
    System.out.println(customer);
    sqlSession.close();
}

POJO

  • 當這些參數屬於我們業務POJO時,我們直接傳遞POJO

​ 示例

public void insertCustom(Customer customer);	

@Test
public void insert(){
    SqlSession sqlSession = MybatisUtils.openSession();
    Customer customer = new Customer();
    customer.setCust_name("后裔2");
    customer.setCust_phone("18907897879");
    sqlSession.insert("insertCustom",customer);
    //當要改動數據庫當中的記錄時,執行sql時要自己提交事務
    //手動提交事務
    sqlSession.commit();
    System.out.println(customer);
    sqlSession.close();
}

<!--添加-->
<insert id="insertCustom" parameterType="com.le.domain.Customer">
	insert into `customer`(cust_name,cust_profession,cust_phone,email)
	values (#{cust_name},#{cust_profession},#{cust_phone},#{email})
</insert>

Map

  • 我們也可以封裝多個參數為map,直接傳遞

​ 示例

public Customer queryCustomerById(Map<String,Object> map);

@Test
public void test(){
	SqlSession sqlSession = MybatisUtils.openSession();
	CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
	HashMap<String, Object> hashMap = new HashMap<>();
	hashMap.put("cust_id",1);
	hashMap.put("cust_name","魯班");
	Customer customer = mapper.getCustomerWithID(hashMap);*/
	System.out.println(customer);
	sqlSession.close();
}
<!--根據cust_id 和 cust_name查詢客戶-->
<select id="queryCustomerById"
		resultType="com.le.domain.Customer">
  SELECT * FROM `customer` WHERE cust_id  = #{cust_id} and cust_name=#{cust_name}
</select>	

參數傳遞源碼分析

  • 會把參數給放到一個數組當中

  • 如果一個參數, 內部處理時,會自動把該參數范圍

  • 如果是多個參數,內部會做判斷

  • 判斷是否有@param注解

​ 如果沒有@param注解
​ 沒有注解的話, 就直接使用arg0 arg1...為key 放到map中

​ 並且還會以param1和param2...為key放一份到map中

​ 如果有@param注解
​ 如果有注解的話, 會使用注解當中的值,替換掉默認的arg0和arg1
​ 使用@param中的值,做為key 放到一個map當中
​ 並且還會以param1和param2...為key放一份到map中

MaBatis核心配置文件

properties標簽

  • 定義屬性及讀取屬性文件

​ 示例

<!-- 是用resource屬性加載外部配置文件 -->
<properties resource="db.properties">
	<!-- 在properties內部用property定義屬性 -->
	<!-- 如果外部配置文件有該屬性,則內部定義屬性被外部屬性覆蓋 -->
	<property name="driver" value="com.mysql.jdbc.Driver" />
	<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
	<property name="username" value="root" />
	<property name="password" value="1234" />
</properties>

settings標簽

  • 這是 MyBatis 中極為重要的調整設置,它們會改變 MyBatis 的運行時行為

​ 示例

package com.le.domain;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Setter@Getter@ToString
public class Customer {
    private Integer cust_id;
    private String cust_name;
    private String cust_profession;
    private String cust_phone;
    private String email;
}

<!-- 用來配置MyBatis中一些設置 -->
<!-- 開啟駝峰映射,為自定義的SQL語句服務 -->
<!-- 設置其用數據庫字段下划線映射到jaba對象的駝峰式命名屬性,默認為false -->
<settings>
    <!-- 打印查詢語句 -->
    <setting name="logImpl" value="STDOUT_LOGGING"/>
    <!--開啟駝峰命名法-->
	<setting name="mapUnderscoreToCamelCase" value="true">
</settings>

typeAliases標簽

  • 類型別名是為 Java 類型設置一個短的名字
  • 定義單個別名
<!--定義別名-->
<typeAliases>
    <!--單個別名定義-->
    <typeAlias alias="Customer" type="com.le.domain.Customer"/>
</typeAliases>		

<!--查詢用戶 ID-->
<select id="getCustomerWithID"  resultType="Customer" >
	select * from `customers` where cust_id = #{id} and cust_name=#{name}
</select>

  • 批量別名定義

    ​ 如果當前包類與子包類重名,會有異常
    ​ 可以在類上使用注解@Alias("別名")

<!--定義別名-->
<typeAliases>
    <!--批量定義別名, 別名為類名(大小寫不敏感)-->
    <package name="com.le.domain"/>
</typeAliases>	

typeHandlers標簽

  • 無論是 MyBatis 在預處理語句(PreparedStatement)中設置一個參數時,
  • 還是從結果集中取出一個值時, 都會用類型處理器將獲取的值以合適的方式轉換成 Java 類型。
  • JDK1.8之后實現全部的JSR310規范
  • 日期時間處理上,我們可以使用MyBatis基於JSR310(Date and Time API)
  • 編寫的各種日期時間類型處理器。
  • MyBatis3.4以前的版本需要我們手動注冊這些處理器,以后的版本都是自動注冊的

Plugins標簽

  • 插件是MyBatis提供的一個非常強大的機制,
  • MyBatis 允許你在已映射語句執行過程中的某一點進行攔截調用。
  • 通過插件來修改MyBatis的一些核心行為。

Environments標簽

  • MyBatis可以配置多種環境,比如開發、測試和生產環境需要有不同的配置。
  • 每種環境使用一個environment標簽進行配置並指定唯一標識符
  • 可以通過environments標簽中的default屬性指定一個環境的標識符來快速的切換環境
  • Environment子標簽

transactionManager事務管理
	Type有以下取值
	JDBC
		使用JDBC 的提交和回滾設置,依賴於從數據源得到的連接來管理事務范圍
	MANAGED
		不提交或回滾一個連接、讓容器來管理事務的整個生命周期
		ManagedTransactionFactory
	自定義
		實現TransactionFactory接口 
		type=全類名/別名
		
dataSource數據源
	type有以下取值
	UNPOOLED
		不使用連接池UnpooledDataSourceFactory
	POOLED
		使用連接池PooledDataSourceFactory
	JNDI
		在EJB 或應用服務器這類容器中查找指定的數據源
	自定義
		實現DataSourceFactory接口,定義數據源的獲取方式
		
實際開發
	實際開發中我們使用Spring管理數據源
	並進行事務控制的配置來覆蓋上述配置 
<!-- spring整合后 environments配置將廢除 使用spring中的連接池 -->
<environments default="development">
    <environment id="development">
        <!-- 使用jdbc事務管理 -->
        <transactionManager type="JDBC" />
        <!-- 數據庫連接池 -->
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driver}" />
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
        </dataSource>
    </environment>

    <environment id="test">
        <!-- 使用jdbc事務管理 -->
        <transactionManager type="JDBC" />
        <!-- 數據庫連接池 -->
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driver}" />
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
        </dataSource>
    </environment>
</environments>

databaseIDProvider標簽

​ MyBatis 可以根據不同的數據庫廠商執行不同的語句。
​ 可以通過databaseIDProvider標簽來進行設置

<databaseIdProvider type="DB_VENDOR">
	<property name="MYSQL" value="mysql"/>
	<property name="DB2" value="db2"/>
	<property name="Oracle" value="oracle" />
	<property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>

​ 示例

<!--查詢用戶 ID-->
<select id="getAllCustomer"  resultType="Customer" databaseId="mysql">
	select * from `customers`
</select>		

mappers標簽

resource屬性

​ 使用相對於類路徑的資源

<!--加載映射文件-->
<mappers>
    <mapper resource="com/le/mapping/CustomerMapping.xml"></mapper>
</mappers>		

class屬性

  • 使用mapper接口類路徑
  • 此種方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中
<!--加載映射文件-->
<mappers>
    <mapper class="com.le.mapping.CustomerMapping"></mapper>
</mappers>	

package子標簽

  • 指定包下的所有mapper接口
  • 此種方法要求mapper接口名稱和mapper映射文件名稱相同,且放在同一個目錄中
<!--加載映射文件-->
<mappers>
    <package name="com.le.mapping"/>
</mappers>	

輸出類型

輸出簡單類型

<!--查詢總數-->
<select id="getAccountCustomer" resultType="Integer">
	select count(*) from customer;
</select>

Map

第1種形式

  • key:是列名

  • value:是列名對應的值

    示例

public Map<String,Object> getCustomerWithId(Integer id);
<select id="getCustomerWithId" resultType="java.util.Map">
	select * from customer where cust_id=#{id}
</select>
@Test
public void test(){
	SqlSession sqlSession = MybatisUtils.openSession();
	CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
	Map<String, Object> customer = customerMapper.getCustomerWithId(2);
	System.out.println(customer);
	sqlSession.close();
}

第2種形式

  • Map<key,自定義對象>
  • key為自己指定的數據庫中的列值

​ 示例

@MapKey("cust_name")
public Map<Integer,Customer> getAllCustomer();

<select id="getAllCustomer" resultType="com.le.domain.Customer">
	select * from customer;
</select>

@Test
public void test(){
	SqlSession sqlSession = MybatisUtils.openSession();
	CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
	Map<Integer, Customer> allCustomer = customerMapper.getAllCustomer();
	for(Integer integer:allCustomer.keySet())
	{
		System.out.println("key="+integer+" value="+allCustomer.get(integer));
	}
	sqlSession.close();
}


resultMap

  • 只有在寫輸出時使用的都是resultType
  • 但是resultType要求必須得要字段名稱和數據庫當中的名稱一致時才能有值,否則為null
  • 如果sql查詢字段名和pojo的屬性名不一致,可以通過resultMap將字段名和屬性名作一個對應關系
  • 表名與domain
package com.le.domain;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Setter@Getter@ToString
public class Customer {
    private Integer cust_ids;
    private String cust_names;
    private String cust_professions;
    private String cust_phones;
    private String email;
}

<resultMap id="customerMap" type="Customer">
	<id column="cust_id" property="cust_ids"/>
	<result column="cust_name" property="cust_names"/>
	<result column="cust_profession" property="cust_professions"/>
	<result column="cust_phone" property="cust_phones"/>
	<result column="email" property="email"/>
</resultMap>

<select id="getCustomer" resultMap="customerMap">
	select * from customer where cust_id=#{id}
</select>

@Test
public void test(){
	SqlSession sqlSession = MybatisUtils.openSession();
	CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
	Customer customer = customerMapper.getCustomer(2);
	System.out.println(customer);
	sqlSession.close();
}



多表操作

ManyToOne

關系表

查詢

分步查詢
第一步 先查出所有的訂單
<resultMap id="myOrder" type="Order">
	<id property="order_id" column="order_id"/>
	<result property="order_name" column="order_name"/>
	<result property="order_num" column="order_name"/>
	<!--分步查詢-->
	<association property="customer" javaType="Customer"
				 select="com.le.mapper.CustomerMapper.getCustomerWithId"
				 column="cust_id">
	</association>
</resultMap>

<select id="getOrders" resultMap="myOrder">
	select * from `order`
</select>				
第二步 根據id查出對應客戶
<mapper namespace="com.le.mapper.CustomerMapper">
	<!--根據id獲取客戶-->
	<select id="getCustomerWithId" resultType="com.le.domain.Customer">
		SELECT * from customer WHERE cust_id = #{id}
	</select>
</mapper>		

左連接查詢
查詢所有的訂單及訂單所對應的客戶
  • 左連接
  • 把左邊表的數據全部查出,右邊表只查出滿足條件的記錄
應對sql
SELECT * FROM `order` as o LEFT JOIN customer as c on o.cus_id = c.cust_id;
建立domain
package com.le.domain;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Setter@Getter@ToString
public class Order {
    private Integer order_id;
    private String order_name;
    private String order_num;
    private Customer customer;
}
建立Mapping映射
<resultMap id="orderMap" type="Order">
    <id property="order_id" column="order_id"/>
    <result property="order_name" column="order_name"/>
    <result property="order_num" column="order_name"/>
    <!--關聯對象賦值-->
    <association property="customer" javaType="Customer">
        <id property="cust_id" column="cust_id"/>
        <result property="cust_name" column="cust_name"/>
        <result property="cust_profession" column="cust_profession"/>
        <result property="cust_phone" column="cust_phone"/>
        <result property="email" column="email"/>
    </association>
</resultMap>

<!--查詢所有訂單-->
<select id="getAllOrders" resultMap="orderMap">
    SELECT * from `order` as o LEFT JOIN `customer` c on o.cust_id = c.cust_id;
</select>	

測試類

@Test
public void test(){
    SqlSession sqlSession = MybatisUtils.openSession();
    OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
    List<Order> allOrders = orderMapper.getAllOrders();
    for (Order order : allOrders) {
        System.out.println(order);
    }
    sqlSession.close();
}
分部查詢懶加載

<!--延遲加載的全局開關。當開啟時,所有關聯對象都會延遲加載。-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--當開啟時,任何方法的調用都會加載該對象的所有屬性。否則,每個屬性會按需加載-->
<setting name="aggressiveLazyLoading" value="false"/>
<!--指定哪個對象的方法觸發一次延遲加載。-->
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode"/>

添加

添加客戶

<!--保存客戶-->
<insert id="insertCustomer" parameterType="Customer"
        useGeneratedKeys="true"
        keyColumn="cust_id"
        keyProperty="cust_id">
    insert into `customer`(cust_name,cust_profession,cust_phone,email)
    values (#{cust_name},#{cust_profession},#{cust_phone},#{email})
</insert>
設置關系(外鍵沒有賦值上)
@Test
public void test(){
	SqlSession sqlSession = MybatisUtils.openSession();
	CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
	OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
	
	Customer customer = new Customer();
	customer.setCust_name("新客戶001");
	customer.setCust_phone("137090909090");
	customer.setEmail("123123@163.com");
	customer.setCust_profession("新職業001");

	/*先添加客戶  獲取客戶生成的id  再去添加訂單*/
	customerMapper.insertCustomer(customer);

	Order order = new Order();
	order.setOrder_name("新訂單001");
	order.setOrder_num("20000001001");
	/*設置關系 */
	order.setCustomer(customer);
	System.out.println(customer);
	/*保存訂單*/
	orderMapper.insertOrder(order);
	sqlSession.commit();
	sqlSession.close();
}
添加訂單
<!--保存訂單-->
<!-- useGeneratedKeys="true"把新增加的主鍵賦值到自己定義的keyProperty(id)中 -->
<insert id="insertOrder" 
		parameterType="Order"
        useGeneratedKeys="true"
        keyColumn="order_id"
        keyProperty="order_id">
    insert into `order`(order_name,order_num,cust_id)
    values (#{order_name},#{order_num},#{customer.cust_id})
</insert>

OnToMany

查詢

查詢客戶和客戶訂單

sql語句
SELECT * FROM customer as c LEFT JOIN `order` as o  on c.cust_id = o.cust_id;
映射

<resultMap id="custMap" type="Customer">
    <id column="cust_id" property="cust_id"/>
    <result column="cust_name" property="cust_name"/>
    <result column="cust_profession" property="cust_profession"/>
    <result column="cust_phone" property="cust_phone"/>
    <result column="email" property="email"/>
    <collection property="orders" ofType="Order">
        <id column="order_id" property="order_id"/>
        <id column="order_name" property="order_name"/>
        <id column="order_num" property="order_num"/>
    </collection>
</resultMap>
<!--查詢所有客戶-->
<select id="getAllCustomers" resultMap="custMap">
    select* from `customer` as c LEFT JOIN `order` as o ON c.cust_id = o.cust_id;
</select>
測試

@Test
public void test4(){
    /*查詢所有客戶*/
    SqlSession sqlSession = MybatisUtils.openSession();
    CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
    List<Customer> allCustomers = customerMapper.getAllCustomers();
    for (Customer allCustomer : allCustomers) {
        System.out.println(allCustomer);
    }
    sqlSession.close();
}

添加

保存數據
/*保存客戶*/
public void insertCustomer(Customer customer);

<!--保存客戶-->
<insert id="insertCustomer" 
		parameterType="Customer"
        useGeneratedKeys="true"
        keyColumn="cust_id"
        keyProperty="cust_id">
    insert into `customer`(cust_name,cust_profession,cust_phone,email)
    values (#{cust_name},#{cust_profession},#{cust_phone},#{email})
</insert>

/*保存訂單*/
public void insertOrder(Order order);

<!--保存訂單-->
<!-- useGeneratedKeys="true"把新增加的主鍵賦值到自己定義的keyProperty(id)中 -->
<insert id="insertOrder" 
		parameterType="Order"
        useGeneratedKeys="true"
        keyColumn="order_id"
        keyProperty="order_id">
    insert into `order`(order_name,order_num,cust_id)
    values (#{order_name},#{order_num},#{customer.cust_id})
</insert>	
維護外鍵

/*更新與客戶的關系*/
public void updateCustId(@Param("orderId") Integer orderId, @Param("custId") Integer custId);		
<!--更新關系-->
<update id="updateCustId">
    update `order` set `cust_id`=#{custId} where `order_id`=#{orderId}
</update>
管理關系
@Test
public void test5(){
    SqlSession sqlSession = MybatisUtils.openSession();
    CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
    OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
    Customer customer = new Customer();
    customer.setCust_name("新客戶");

    Order order1 = new Order();
    order1.setOrder_name("訂單2");

    Order order2 = new Order();
    order2.setOrder_name("訂單2");

    customer.getOrders().add(order1);
    customer.getOrders().add(order2);

    /*保存數據*/
    customerMapper.insertCustomer(customer);
    orderMapper.insertOrder(order1);
    orderMapper.insertOrder(order2);

    /*更新關系*/
    for (Order order : customer.getOrders()) {
        orderMapper.updateCustId(order.getOrder_id(),customer.getCust_id());
    }
    sqlSession.commit();
    sqlSession.close();
}			

刪除

  • 刪除時一定要先打破關系再做刪除操作

    示例

/*根據id刪除客戶*/
public void deleteCustomer(Integer id);		

<!--根據id刪除客戶-->
<delete id="deleteCustomer">
    delete from `customer` where cust_id=#{id}
</delete>
/*打破跟客戶關系*/
public void updateRelationCustomer(Integer custId);
<!--打破跟客戶關系-->
<update id="updateRelationCustomer">
    update `order` set cust_id=null where cust_id=#{custId}
</update>	

@Test
public void test(){
    SqlSession sqlSession = MybatisUtils.openSession();
    CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
    OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
    //一對多刪除之前  要先打破關系
    orderMapper.updateRelationCustomer(36);
    /*刪除客戶*/
    customerMapper.deleteCustomer(36);
    sqlSession.commit();
    sqlSession.close();
}



ManyToMany

關系表

package com.le.domain;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.ArrayList;
import java.util.List;

@Setter@Getter@ToString
public class Teacher {
    private Integer teacher_id;
    private String teacher_name;
    private List<Student> students = new ArrayList<>();
}
package com.le.domain;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Setter@Getter @ToString
public class Student {
    private Integer stu_id;
    private String stu_name;
}

查詢

分步查詢
查詢出指定的老師
public interface TeacherMapper {
    /*查詢指定的老師*/
    public Teacher getTeacherWithId(Integer id);
}
<!--查詢指定的老師-->
<select id="getTeacherWithId" resultMap="teacherMap2">
    SELECT * from teacher WHERE teacher_id = #{id};
</select>
<resultMap id="teacherMap2" type="Teacher">
    <id column="teacher_id" property="teacher_id"/>
    <result column="teacher_name" property="teacher_name"/>
    <collection property="students" ofType="Student"
                select="com.le.mapper.StudentMapper.getStuByTeach"
                column="teacher_id"/>
</resultMap>	
根據老師id查詢出所有學生
public interface StudentMapper {
    /*根據老師id查詢學生*/
    public List<Student>getStuByTeach(Integer id);
}

<select id="getStuByTeach" resultType="com.le.domain.Student">
      SELECT * from student where stu_id in(SELECT stu_id from stu_teacher_rel where teacher_id = #{id})
</select>		

查詢

@Test
public void test2(){
    SqlSession sqlSession = MybatisUtils.openSession();
    TeacherMapper teacherMapper = sqlSession.getMapper(TeacherMapper.class);
    Teacher teacher = teacherMapper.getTeacherWithId(2);
    System.out.println(teacher);
    sqlSession.close();
}		
左邊接查詢
public interface TeacherMapper {
    /*查詢老師  並且把關聯的學生也查出來*/
    public List<Teacher>getAllTeachers();
}

<mapper namespace="com.le.mapper.TeacherMapper">
    <!-- 查詢老師  並且把關聯的學生也查出來 -->
    <resultMap id="teacherMap" type="Teacher">
        <id column="teacher_id" property="teacher_id"/>
        <result column="teacher_name" property="teacher_name"/>
        <collection property="students" javaType="list" ofType="Student">
            <id column="stu_id" property="stu_id"/>
            <result column="stu_name" property="stu_name"/>
        </collection>
    </resultMap>

    <select id="getAllTeachers" resultMap="teacherMap">
        SELECT*FROM teacher as t
        LEFT JOIN stu_teacher_rel as r on t.teacher_id = r.teacher_id
        LEFT JOIN student as s ON r.stu_id = s.stu_id
    </select>
</mapper>

添加

添加老師
/*保存老師*/
public void insertTeacher(Teacher teacher);
<!--保存老師-->
<insert id="insertTeacher" parameterType="Teacher"
        useGeneratedKeys="true"
        keyProperty="teacher_id"
        keyColumn="teacher_id">
    insert into`teacher`(teacher_name) values (#{teacher_name})
</insert>
添加學生
/*保存學生*/
public void insertStudent(Student student);
<!--保存學生-->
<insert id="insertStudent" parameterType="Student"
        useGeneratedKeys="true"
        keyProperty="stu_id"
        keyColumn="stu_id">
    insert into `student` (stu_name) values (#{stu_name})
</insert>	
添加中間關系
/*插入關系表*/
public void insertRelation(@Param("stuId") Integer stuId, @Param("teacherId") Integer teacherId);
<!-- 插入關系表 -->
<insert id="insertRelation">
    insert into stu_teacher_rel (stu_id,teacher_id) values (#{stuId},#{teacherId})
</insert>	

動態sql

什么是動態sql

​ 通過mybatis提供的各種標簽方法實現動態拼接sql。

if標簽

需求

根據客戶名和職業查詢客戶
/*根基客戶名稱和職業來查詢*/
public List<Customer> getCustomer(@Param("name") String name, @Param("profession") String profession);
<select id="getCustomer" 
		resultType="com.le.domain.Customer">
	select from customer where cust_name=#{name} ad cust_profession=#{profession}
</select>	
存在問題
  • 有可能傳入的名稱或級別為空
  • 可以使用if標簽來進行判斷
  • 如果前一個條件后面多一個and執行就會報錯(也就是說需要將and分布合理)
<!--if標簽:符合條件會自動把if中的內容拼接到sql之后-->
<select id="getCustomer" 						resultType="com.le.domain.Customer">
    select * from `customer` where
	<if test="name != null and name != ''">
	  `cust_name`=#{name}
	</if>
	<if test="profession != null and profession!=''">
	  and `cust_profession`=#{profession}
	</if>
</select>

Where標簽

  • 去掉第一個前And
<!--where標簽:會自動生成和刪除where  
	還能刪除where后第1個and  
	條件前and去掉 -->
<select id="getCustomer2"
	resultType="com.le.domain.Customer">
	select * from `customer`
	<where>
		<if test="name != null and name != ''">
		  and `cust_name`=#{name}
		</if>
		<if test="profession != null and profession!=''">
		  and `cust_profession`=#{profession}
		</if>
	</where>
</select>

trim標簽

<!--trim標簽:
   prefix:設置前綴  在第一個條件之前加一個前綴
   prefixOverrides: 條件前綴覆蓋 把第一個條件之前的and變成空
   suffix: 設置后綴 在最后一個條件之后加一個后綴
   suffixOverrides: 條件后綴覆蓋  把最后一個條件之后的and變成空
-->
<select id="getCustomer3"
	resultType="com.le.domain.Customer">
    select * from `customer`
    <trim prefix="where" prefixOverrides="and" suffixOverrides="and" >
        <if test="name != null and name != ''">
            and `cust_name`=#{name} and
        </if>
        <if test="profession != null and profession!=''">
           `cust_profession`=#{profession} and
        </if>
    </trim>
</select>

choose標簽

<!--
    choose   只要第一個條件滿足,后面條件都不執行
    when
    otherwise
-->
<select id="getCustomer" resultType="com.le.domain.Customer">
    <include refid="selectID"/>
    <where>
        <choose>
            <when test="profession != null and profession!=''">
                `cust_profession`=#{profession}
            </when>
            <when test="name != null and name != ''">
                `cust_name`=#{name}
            </when>
            <otherwise>1=1</otherwise>
        </choose>
    </where>
</select>

set標簽

<!--
    set標簽:會添加update 中 set  並且它會把最后一個,去掉
-->
<!--更新客戶-->
<update id="updateCustomer">
    update `customer`
    <set>
        <if test="cust_name != null and cust_name !='' ">
            cust_name=#{cust_name},
        </if>
        <if test="cust_profession != null and cust_profession !='' ">
            cust_profession=#{cust_profession},
        </if>
    </set>
    where cust_id=#{cust_id}
</update>

foreach標簽

查詢條件值為指定的值當中

<select id="queryCustomerIn"
	resultType="com.le.domain.Customer">
	<include refid="selectID"/>where `cust_id` in(2,3,5,6);
</select>
<!--注意 在include當中定義的property 取的時候 要使用${} -->
<sql id="selectID">
	<choose>
		<when test="${lk} == 2">
			select cust_name from `customer`
		</when>
		<otherwise>
			select * from `customer`
		</otherwise>
	</choose>
</sql>

給定的值可以以三種形式給出
數組

/*根據id查詢指定的客戶 多個客戶*/
public List<Customer> getCustomers(Integer[] array);
@Test
public void test(){
	SqlSession sqlSession = MybatisUtils.openSession();
	CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
	Integer[] ids = new Integer[4]{2,3,5,6};
	List<Customer> customers = customerMapper.getCustomers(ids);
	for (Customer customer : customers) {
		System.out.println(customer);
	}
	sqlSession.close();
}
<select id="getCustomers" 
	parameterType="Integer[]" resultType="com.le.domain.Customer">
	select * from `customer` where `cust_id` in
	<foreach collection="array" open="(" close=")" separator="," item="item">
		#{item}
	</foreach>
</select>

List
<select id="getCustomers" 
	parameterType="List" resultType="com.le.domain.Customer">
	select * from `customer` where `cust_id` in
	<foreach collection="list" open="(" close=")" separator="," item="item">
		#{item}
	</foreach>
</select>
@Test
public void test(){
	SqlSession sqlSession = MybatisUtils.openSession();
	CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
	ArrayList<Integer> list = new ArrayList<>();
	list.add(2);
	list.add(3);
	list.add(4);
	list.add(6);
	List<Customer> customers = customerMapper.getCustomers(list);
	for (Customer customer : customers) {
		System.out.println(customer);
	}
	sqlSession.close();
}

包裝類VO

​ 創建Vo

package com.le.domain;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.util.List;

@Setter@Getter@ToString
public class QueryVo {
    private Integer[] ids;
    private List<Integer> idList;
}			


​ 測試

<select id="getCustomers" 
	parameterType="QueryVo" resultType="com.le.domain.Customer">
	<include refid="selectID"/> where `cust_id` in
	<foreach collection="idList" open="(" close=")" separator="," item="ids">
		#{ids}
	</foreach>
</select>
@Test
public void test(){
	SqlSession sqlSession = MybatisUtils.openSession();
	CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);

	QueryVo queryVo = new QueryVo();
	queryVo.setIds(new Integer[]{2,3,4,5});
	ArrayList<Integer> arrayList = new ArrayList<>();
	arrayList.add(2);
	arrayList.add(3);
	arrayList.add(4);
	arrayList.add(6);
	queryVo.setIdList(arrayList);
	List<Customer> customers = customerMapper.getCustomers(queryVo);
	for (Customer customer : customers) {
		System.out.println(customer);
	}
	sqlSession.close();
}

bind標簽

<!--
    bind標簽:可以取出傳入的值,重新處理, 賦值給別外一個值
 -->
<select id="getCustomerWithId" resultType="Customer">
    <bind name="newId" value="id+2"/>
    <include refid="selectID">
        <property name="lk" value="2"/>
    </include>  where cust_id=#{newId}
</select>

Sql片段

  • Sql中可將重復的sql提取出來,使用時用include引用即可,最終達到sql重用的目的。
<select id="getCustomerWithId" resultType="Customer">
    <include refid="selectID">
        <property name="lk" value="2"/>
    </include>  where cust_id=#{id}
</select>

<!--注意 在include當中定義的property 取的時候 要使用${} -->
<sql id="selectID">
    <choose>
        <when test="${lk} == 2">
            select cust_name from `customer`
        </when>
        <otherwise>
            select * from `customer`
        </otherwise>
    </choose>
</sql>

緩存

一級緩存

緩存介紹

  • MyBatis中使用緩存來提高其性能。
  • 當查詢數據時, 會先從緩存中取出數據,如果緩存中沒有,再到數據庫當中查詢
  • MyBatis中的緩存分為兩種:一級緩存和二級緩存
  • 一級緩存是sqlSession級別的,二級緩存是mapper級別的

一級緩存

  • 本地緩存 (默認開啟)
  • 在sqlSession沒有關閉之前,再去查詢時, 會從緩存當中取出數據,不會重新發送新的sql

一級緩存失效

  • 如果在查詢之前,執行了增\刪\改 緩存就會失效
  • 手動清空緩存
  • 如果兩次的查詢條件不一樣,緩存也會失效
  • 如果兩個查詢在不同的sqlsession當中

二級緩存

二級緩存介紹

​ 全局作用域緩存 一個namespace對應一個緩存
​ 如果會話關閉,一級緩存的數據會被保存到二級緩存中
​ 不同namespace查出的數據 ,會放到自己對應的緩存中
​ 現在默認也是打開的

二級緩存使用步驟

​ 1.確保在配置文件當中開啟二級緩存
​ 2.在對應的mapper中添加cache標簽

eviction
	回收策略
flushInterval
	刷新間隔
	默認不清空
readOnly
	是否只讀
	true
		告訴Mybatis是只讀操作,不去修改數據
		Mybatis為了加快獲取速度,會直接將緩存的引用將給用, 不安全, 速度快
	false
		非只讀,有可能修改數據
		Mybatis會利用序列化和反序列化復制一份給你   速度慢些
size
	可以存放多少個元素
type
	可以用來指定自定義的緩存

​ 3.POJO需要實現Serializable接口

注意事項

  • 查詢的數據都會先放到一級緩存當中
  • 只有會話關閉,一級緩存中的數據才會轉稱到二級緩存中

緩存相關屬性

cacheEnabled
	只能控制二級緩存的開關
select中useCache
	控制的也是二級緩存是否使用
增刪改標簽中flushCache
	一級和二級都會被清空
	增刪改flushCache默認為true
	查詢flushCache默認為false
sqlSession.clearCache()
	只清除當前session的一級緩存
localCacheScope
	本地緩存作用域
	取值
		SESSION
		STATEMENT
	STATEMENT可以使用它禁用緩存

緩存使用順序

  • 先到二級緩存當中查找
  • 如果二級緩存中沒有,就去找一級緩存
  • 如果一級緩存中也沒有就去到數據庫當中查詢


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM