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可以使用它禁用缓存

缓存使用顺序

  • 先到二级缓存当中查找
  • 如果二级缓存中没有,就去找一级缓存
  • 如果一级缓存中也没有就去到数据库当中查询
posted @ 2019-06-03 15:29  海韵༒听心  阅读(710)  评论(0编辑  收藏  举报