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架构

1296811-20190603152726124-742514400.png

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>   

参数传递源码分析

  • 会把参数给放到一个数组当中

  • 如果一个参数, 内部处理时,会自动把该参数范围

1296811-20190603152735161-861099591.png

  • 如果是多个参数,内部会做判断

  • 判断是否有@param注解

​ 如果没有@param注解
​ 没有注解的话, 就直接使用arg0 arg1...为key 放到map中

​ 并且还会以param1和param2...为key放一份到map中

1296811-20190603152748549-2144987321.png

​ 如果有@param注解
​ 如果有注解的话, 会使用注解当中的值,替换掉默认的arg0和arg1
​ 使用@param中的值,做为key 放到一个map当中
​ 并且还会以param1和param2...为key放一份到map中

1296811-20190603152757203-2067467297.png

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

关系表

1296811-20190603152825259-204827851.png

查询
分步查询
第一步 先查出所有的订单
<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

查询
查询客户和客户订单

1296811-20190603152814677-1626730108.png

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

关系表

1296811-20190603152806875-2032696382.png

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

缓存使用顺序

  • 先到二级缓存当中查找
  • 如果二级缓存中没有,就去找一级缓存
  • 如果一级缓存中也没有就去到数据库当中查询

转载于:https://www.cnblogs.com/mumuyinxin/p/10967833.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值