入门篇. Mybatis应用搭建以及一,二级缓存理解

一.简介

Mybatis是一款轻量级持久层的ORM框架

Object Relational Mapping

二.应用搭建

2.1.mybatis-config全局配置文件,数据库db.properties配置文件
    
2.2.mapper接口以及对于的xml文件

2.3.@Junit测试

 2.1.mybatis-config全局配置文件,数据库db.properties配置文件

<?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>


    <!-- 指定资源文件 -->
    <!-- 参考文档:https://blog.51cto.com/suyanzhu/1916951 -->
    <properties resource="db.properties"></properties>

    <!-- 开启支持缓存,默认值就是true -->
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>

    <!--环境配置-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${conf.driver}"/>
                <property name="url" value="${conf.url}"/>
                <property name="username" value="${conf.username}"/>
                <property name="password" value="${conf.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--<mapper resource="EmpMapper.xml"/>-->
        <mapper class="com.mybatis.wang.mapper.EmpMapper"></mapper>
    </mappers>
    
</configuration>

 db.properties配置文件  

conf.driver=com.mysql.jdbc.Driver
conf.url=jdbc:mysql://localhost:3306/wang_learn
conf.username=root
conf.password=root

2.2.mapper文件

package com.mybatis.wang.mapper;

import com.mybatis.wang.pojo.Emp;
import org.apache.ibatis.annotations.CacheNamespace;
import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.util.List;
import java.util.Map;

// @CacheNamespace 注解的方式开启二级缓存
@CacheNamespace
public interface EmpMapper {

    public Emp selectEmp(Integer id);

    @Select("select * from t_emp where id=${id}")
    public Emp selectEmpByAnno$(Integer id);

    @Select("select * from t_emp where id=#{id}")
    public Emp selectEmpByAnno(Integer id);

    @Select("select * from t_emp where id=#{id}")
    public List<Emp> selectEmpListByAnno(Integer id);

    @Select("select * from t_emp_error where id=#{id}")
    public Emp selectEmpByAnnoError(Integer id);

    @Select("select * from t_emp where id=#{id} and name=#{name}")
    public List<Emp> selectEmpListByMultiParam(@Param("id")Integer id , @Param("name")String name);

    @MapKey("id")
    public Map<Integer, Emp> getAllEmpReturnMap();

    public Emp findEmpByEmpno(Integer empno);

    public int updateEmp(Emp emp);

    public int deleteEmp(Integer empno);

    public int insertEmp(Emp emp);

}

<?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.mybatis.wang.mapper.EmpMapper">

    <!--<cache></cache>-->
    <!--根据id查询Emp实体-->
    <select id="selectEmp" resultType="com.mybatis.wang.pojo.Emp">
        select * from t_emp where id = #{id}
    </select>

    <!-- 返回map结果集 -->
    <select id="getAllEmpReturnMap" resultType="com.mybatis.wang.pojo.Emp">
        select * from `wang_learn`.`t_emp`
    </select>

    <insert id="insertEmp">
        INSERT INTO
        `wang_learn`.`t_emp` (`id`, `name`)
        VALUES (#{id}, #{name});
    </insert>

    <update id="updateEmp">
        UPDATE `wang_learn`.`t_emp`
        SET name=#{name}
        WHERE id=#{id}
    </update>

    <delete id="deleteEmp">
        DELETE FROM `wang_learn`.`t_emp`
        WHERE id=#{id}
    </delete>
</mapper>

注意这里默认情况下mapper.xml文件不会加载到classpath对于的target下面,如果想把接口和mapper文件放在一起,要在pom,xml里面bulid标签中加上如下:

    <build>
        <!--保证mapper的接口和xml在一起-->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

2.3.单元测试

package com.mybatis.wang.test;

import com.mybatis.wang.mapper.EmpMapper;
import com.mybatis.wang.pojo.Emp;
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 org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

public class TestEmpCRUD {

    SqlSessionFactory sqlSessionFactory;

    @Before
    public void before(){
        // 从 XML 中构建 SqlSessionFactory
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    /**
     * 基于StatementId的方式去执行SQL
     *      <mapper resource="EmpMapper.xml"/>
     * @throws IOException
     */
    @Test
    public void test01() {
        try (SqlSession session = sqlSessionFactory.openSession()) {
            Emp emp = (Emp) session.selectOne("com.mybatis.wang.mapper.EmpMapper.selectEmp", 1);
            System.out.println(emp);
        }
    }

    @Test
    public void test01_list() {
        try (SqlSession session = sqlSessionFactory.openSession()) {
            EmpMapper mapper = session.getMapper(EmpMapper.class);
            List list = mapper.selectEmpListByAnno(1);// com.mybatis.wang.mapper.EmpMapper.selectEmpListByAnno
            System.out.println(list);

            List secondQueryList = mapper.selectEmpListByAnno(1);
            System.out.println("secondQueryList = " + secondQueryList);

        }
    }

    /**
     * 在一个sqlsession里面,连续查询同一个sql二次,参数一致的情况下
     *
     * 第一次查询库了,第二次走了 一级缓存
     * (二级缓存是mapper应用级别,针对多个sqlsession都有效,默认情况下不开启二级缓存)
     */
    @Test
    public void test01_learnCacheTwo() {
        try (SqlSession session = sqlSessionFactory.openSession()) {
            EmpMapper mapper = session.getMapper(EmpMapper.class);
            Emp firstQuery = mapper.selectEmp(1);// com.mybatis.wang.mapper.EmpMapper.selectEmpListByAnno
            System.out.println(firstQuery);

            Emp secondQuery = mapper.selectEmp(1);
            System.out.println("secondQuery = " + secondQuery);
        }
    }


    @Test
    public void test03(){
        try (SqlSession session = sqlSessionFactory.openSession()) {
            EmpMapper mapper = session.getMapper(EmpMapper.class);
            Emp emp = mapper.selectEmpByAnno(2);
            System.out.println(emp);
        }
    }

    @Test
    public void test04(){
        try (SqlSession session = sqlSessionFactory.openSession()) {
            EmpMapper mapper = session.getMapper(EmpMapper.class);
            Emp emp = mapper.selectEmpByAnnoError(3);
            System.out.println(emp);
        }
    }

    /**
     * ${} 以字符串拼接的形式形成SQL,会有注入问题
     *
     * #{} 预编译
     *
     */
    @Test
    public void test05_query$(){
        try (SqlSession session = sqlSessionFactory.openSession()) {
            EmpMapper mapper = session.getMapper(EmpMapper.class);
            Emp emp = mapper.selectEmpByAnno$(3);
            System.out.println(emp);
        }
    }

    @Test
    public void test05_queryMultiParam(){
        try (SqlSession session = sqlSessionFactory.openSession()) {
            EmpMapper mapper = session.getMapper(EmpMapper.class);
            List<Emp> listByMultiParam = mapper.selectEmpListByMultiParam(10, "test_xiaowang");
            System.out.println(listByMultiParam);
        }
    }

    @Test
    public void test05_queryEmpReturnMap(){
        try (SqlSession session = sqlSessionFactory.openSession()) {
            EmpMapper mapper = session.getMapper(EmpMapper.class);
            Map<Integer, Emp> allEmpReturnMap = mapper.getAllEmpReturnMap();
            System.out.println(allEmpReturnMap);
        }
    }

    @Test
    public void test05_Insert(){
        try (SqlSession session = sqlSessionFactory.openSession()) {
            EmpMapper mapper = session.getMapper(EmpMapper.class);
            Emp empPojo = new Emp();
            empPojo.setId(11);
            empPojo.setName("emp【11】");
            int i = mapper.insertEmp(empPojo);
            System.out.println("影响行数===========> " + i );
            System.out.println("commit提交之前");
            session.commit();
        }
    }
}

三.demo部分结果

 四.小结

1.请注意接口和xml文件一致性,都要加载到classpath中

2.一级缓存是基于session级别,二级缓存基于mapper应用级别(默认不开启)

五.源码流程理解

1. 首先会去解析全局配置文件,然后去解析对应的mapper.xml文件,都加载到一个configuration的对象中,然后通过这个configuration去构造SqlSessionFactory。

2. 通过SqlSessionFactory得到Sqlsession对象,这里是通过SqlSession里面的执行器Executor去干活的。(org.apache.ibatis.executor.Executor 种类用途后续详细介绍)

3.一级缓存基于BaseExecutor里面的localCache变量,每次事务的提交和回滚之前都会清空localCache。

 

 

二级缓存基于CachingExecutor里面的事务管理缓存tcm对象。

 

4.关于Cache的理解,它也是一层包裹着一层,其目的是职责单一性。干活是也会逐级委托(delegate.getObject(key)) 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值