Mybatis基础回顾和高级应用

Mybatis相关概念回顾

ORM:表示对象-关系映射的缩写。

Mybatis:一款基于ORM的半自动轻量级持久化框架,支持定制化SQL,存储过程以及高级映射。

Mybatis环境

Mybatis官网地址:http://www.mybatis.org/mybatis-3/

首先我们需要导入Mybatis的坐标

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.guslegend</groupId>
  <artifactId>MybatisQucickStart</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>MybatisQucickStart</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
    <java.version>11</java.version>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <dependencies>

    <!--mybatis坐标-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.5</version>
    </dependency>
    <!--mysql驱动坐标-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
      <scope>runtime</scope>
    </dependency>
    <!--单元测试坐标-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <!--⽇志坐标-->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.12</version>
    </dependency>
    <!--Lombok 坐标-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.10</version>
    </dependency>

  </dependencies>
</project>

我们需要编写核心配置文件sqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3307/test?useSSL=false&amp;serverTimezone=Asia/Shanghai&amp;characterEncoding=utf8&amp;allowPublicKeyRetrieval=true"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>

</configuration>

编写测试类

public class MybatisTest {

    @Test
    public void selectAll() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mapper/sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<UserDo> userDoList = sqlSession.selectList("com.guslegend.mapper.UserMapper.findAll");
        for (UserDo userDo : userDoList) {
            System.out.println(userDo);
        }
        sqlSession.close();
    }
}

Mybatis的CRUD

public class MybatisTest {

    @Test
    public void testUpdate() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mapper/sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserDo userDo = new UserDo();
        userDo.setName("guslegend");
        userDo.setId(1);
        int update = sqlSession.update("com.guslegend.mapper.UserMapper.update", userDo);
        System.out.println(update);
    }


    /**
     * 测试删除
     */
    @Test
    public void testDel() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mapper/sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserDo userDo = new UserDo();
        userDo.setName("guslegend");
        userDo.setId(5);
        int del = sqlSession.delete("com.guslegend.mapper.UserMapper.del", userDo);
        System.out.println(del);
    }

    /**
     * 测试查询
     */
    @Test
    public void select() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mapper/sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserDo userDo = sqlSession.selectOne("com.guslegend.mapper.UserMapper.findById", 1);
        System.out.println(userDo);
    }

    /**
     * 测试插入
     */
    @Test
    public void add() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mapper/sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserDo userDo = new UserDo();
        userDo.setName("guslegend");
        userDo.setId(5);
        int insert = sqlSession.insert("com.guslegend.mapper.UserMapper.add", userDo);
        System.out.println(insert);
    }

    /**
     * 测试查询所有
     */
    @Test
    public void selectAll() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mapper/sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<UserDo> userDoList = sqlSession.selectList("com.guslegend.mapper.UserMapper.findAll");
        for (UserDo userDo : userDoList) {
            System.out.println(userDo);
        }
        sqlSession.close();
    }
}
<?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.guslegend.mapper.UserMapper">

    <select id="findAll" resultType="com.guslegend.model.UserDo">
        select * from user
    </select>

    <!--    增加-->
    <insert id="add" parameterType="com.guslegend.model.UserDo">
        insert into user values (#{id},#{name})
    </insert>

    <!--    删除-->
    <delete id="del" parameterType="java.lang.Integer">
        delete from user where id=#{id}
    </delete>

    <!--    修改-->
    <update id="update" parameterType="com.guslegend.model.UserDo">
        update user set name=#{name} where id=#{id}
    </update>

    <select id="findById" resultType="com.guslegend.model.UserDo">
        select * from user where id=#{id}
    </select>

</mapper>

注意:除了查询都需要开启事务 SqlSession sqlSession = sqlSessionFactory.openSession(true);

相关配置文件回顾

Mybatis相关API

InputStream inputStream = Resources.getResourceAsStream("mapper/sqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();

Resources类可以帮助我们在类路径下,文件系统中加载资源文件。

SqlSessionFactory里面有多方法创建SqlSession实例。

SqlSession可以进行语句的增删改查回顾事务,获取映射实例方法等。

执⾏语句的⽅法主要有:
<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
int insert(String statement, Object parameter)
int update(String statement, Object parameter)
int delete(String statement, Object parameter)

操作事务的⽅法主要有:
void commit() 
void rollback()

DAO层传统开发方式

UserMapper.java

public interface UserMapper {

    List<UserDo> findAll() throws Exception;
}

UserMapperImpl.java

public class UserMapperImpl implements UserMapper {

    @Override
    public List<UserDo> findAll() throws Exception {
        InputStream inputStream = Resources.getResourceAsStream("mapper/sqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        SqlSession session = sqlSessionFactory.openSession();
        List<UserDo> userDoList = session.selectList("com.guslegend.mapper.UserMapper.findAll");
        return userDoList;
    }
}

测试传统方法

DAO层代理开发方式

Dao代理方式开发式企业主流的开发方式。这里Mapper层相当于Mapper接口。

1) Mapper.xml⽂件中的namespace与mapper接⼝的全限定名相同

2) Mapper接⼝⽅法名和Mapper.xml中定义的每个statement的id相同

3) Mapper接⼝⽅法的输⼊参数类型和mapper.xml中定义的每个sql的parameterType的类型相同

4) Mapper接⼝⽅法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

    @Test
    public void testUserMapper2() throws Exception{
        InputStream inputStream = Resources.getResourceAsStream("mapper/sqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<UserDo> userDoList = userMapper.findAll();
        for (UserDo userDo : userDoList) {
            System.out.println(userDo);
        }
    }

常见Mybatis配置解析

environments标签

其中,事务管理器(transactionManager)类型有两种:

•JDBC:这个配置就是直接使⽤了JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作⽤域。

•MANAGED:这个配置⼏乎没做什么。它从来不提交或回滚⼀个连接,⽽是让容器来管理事务的整个⽣命周期

(⽐如 JEE 应⽤服务器的上下⽂)。 默认情况下它会关闭连接,然⽽⼀些容器并不希望这样,因此需要将

closeConnection 属性设置为 false 来阻⽌它默认的关闭⾏为。

其中,数据源(dataSource)类型有三种:

•UNPOOLED:这个数据源的实现只是每次被请求时打开和关闭连接。

•POOLED:这种数据源的实现利⽤“池”的概念将 JDBC 连接对象组织起来。

•JNDI:这个数据源的实现是为了能在如 EJB 或应⽤服务器这类容器中使⽤,容器可以集中或在外部配置数据源,

然后放置⼀个 JNDI 上下⽂的引⽤。

mapper标签

加载映射的方法

使⽤相对于类路径的资源引⽤,例如:
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>

使⽤完全限定资源定位符(URL),例如:
<mapper url="file:///var/mappers/AuthorMapper.xml"/>

使⽤映射器接⼝实现类的完全限定类名,例如:
<mapper class="org.mybatis.builder.AuthorMapper"/>

将包内的映射器接⼝实现全部注册为映射器,例如:
<package name="org.mybatis.builder"/>

Properties标签

在实际开发过程中,我们通常会将数据库配置信息单独抽取为一个properties文件。

typeAliases标签

Mybatis复杂映射关系

用户表和订单表的关系为:一个用户有多个订单,一个订单只属于一个用户。

一对一映射

@Data
public class OrderVO {

    private Integer id;

    private Double total;

    private Date orderTime;

    private UserDO userDO;
}
<mapper namespace="com.guslegend.mapper.OrderMapper">

    <resultMap id="orderMap" type="com.guslegend.vo.OrderVO">
        <result column="id" property="id"/>
        <result column="total" property="total"/>
        <result column="ordertime" property="orderTime"/>
        <association property="userDO" javaType="com.guslegend.model.UserDO">
            <result column="uid" property="id"/>
            <result column="uname" property="name"/>
        </association>
    </resultMap>

    <select id="findAllOrderByOrderId" resultMap="orderMap">
        select * from orders o , user u where o.uid = u.id
    </select>

</mapper>
    @Test
    public void test1() throws Exception{
        InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
        List<OrderVO> orderVOList = orderMapper.findAllOrderByOrderId();
        for (OrderVO orderVO : orderVOList) {
            System.out.println(orderVO);
        }

    }
OrderVO(id=1, total=50.0, orderTime=Wed Nov 12 00:00:00 CST 2025, userDO=UserDO(id=1, name=null))
OrderVO(id=2, total=100.0, orderTime=Thu Nov 13 00:00:00 CST 2025, userDO=UserDO(id=1, name=null))
OrderVO(id=4, total=1000.0, orderTime=Mon Dec 01 00:00:00 CST 2025, userDO=UserDO(id=2, name=null))

一对多映射

@Data
public class UserVO {

    private Integer id;

    private String name;

    private List<OrderDO> orders;
}
<mapper namespace="com.guslegend.mapper.UserMapper">

    <select id="findAll" resultType="UserDO">
        select * from user
    </select>

    <resultMap id="userMap" type="com.guslegend.vo.UserVO">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <collection property="orders" ofType="com.guslegend.model.OrderDO">
            <result column="oid" property="id"/>
            <result column="total" property="total"/>
            <result column="ordertime" property="orderTime"/>
        </collection>
    </resultMap>

    <select id="findAllOrderByUserId" resultMap="userMap">
        select * from user u , orders o where u.id = o.uid
    </select>

</mapper>
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<UserVO> userVOList = userMapper.findAllOrderByUserId();
        for (UserVO userVO : userVOList) {
            System.out.println(userVO);
        }
UserVO(id=1, name=guslegend, orders=[OrderDO(id=null, total=50.0, orderTime=Wed Nov 12 00:00:00 CST 2025), OrderDO(id=null, total=100.0, orderTime=Thu Nov 13 00:00:00 CST 2025)])
UserVO(id=2, name=xiaozhang, orders=[OrderDO(id=null, total=1000.0, orderTime=Mon Dec 01 00:00:00 CST 2025)])

多对多查询

@Data
public class UserVO {

    private Integer id;

    private String name;

    private List<RoleDO> roles;
}
    <resultMap id="userRoleMap" type="com.guslegend.vo.UserVO">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <collection property="roles" ofType="com.guslegend.model.RoleDO">
            <result column="rid" property="id"/>
            <result column="rolename" property="roleName"/>
        </collection>
    </resultMap>

    <select id="findAllUserAndRole" resultMap="userRoleMap">
    select * from user u ,sys_role r , sys_user_role ur where u.id = ur.userid and r.id = ur.roleid

    </select>
    @Test
    public void test3() throws Exception{
        InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<UserVO> userVOList = userMapper.findAllUserAndRole();
        for (UserVO userVO : userVOList) {
            System.out.println(userVO);
        }
    }
UserVO(id=1, name=guslegend, orders=null, roles=[RoleDO(id=null, roleName=CTO), RoleDO(id=null, roleName=CEO)])
UserVO(id=2, name=xiaozhang, orders=null, roles=[RoleDO(id=null, roleName=CTO), RoleDO(id=null, roleName=CEO)])

Mybatis注解开发

注解开发的形式可以减少我们编写Mapper映射文件。

@Inset,@Update,@Delete,@Select,@Result(实现结果集封装),@Results(可以与@Result一起使用,封装多个结果集),@One(实现一对一结果集封装),@Many(实现一对多结果集封装)

增删改查

public interface UserMapper {

    List<UserDO> findAll() throws Exception;

    List<UserVO> findAllOrderByUserId() throws Exception;

    List<UserVO> findAllUserAndRole() throws Exception;

    @Insert("insert into user values (#{id}, #{name})")
    int add(UserDO userDO) throws Exception;

    @Delete("delete from user where id = #{id}")
    int del(UserDO userDO) throws Exception;

    @Update("update user set name = #{name} where id = #{id}")
    int update(UserDO userDO) throws Exception;

    @Select("select * from user where id = #{id}")
    UserDO findById(Integer id) throws Exception;

}
public class MybatisTest2 {


    private UserMapper userMapper;


    @Before
    public void before() throws Exception {
        InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        SqlSession session = sqlSessionFactory.openSession(true);
        userMapper = session.getMapper(UserMapper.class);
    }

    @Test
    public void testAdd() throws Exception {
        UserDO userDO = new UserDO();
        userDO.setId(10);
        userDO.setName("xiaozhangzhang");
        int add = userMapper.add(userDO);
        System.out.println(add);
    }

    @Test
    public void testDel() throws Exception {
        UserDO userDO = new UserDO();
        userDO.setId(10);
        int del = userMapper.del(userDO);
        System.out.println(del);
    }

    @Test
    public void testUpdate() throws Exception {
        UserDO userDO = new UserDO();
        userDO.setId(10);
        userDO.setName("xiaozhangzhang2");
        int update = userMapper.update(userDO);
        System.out.println(update);
    }

    @Test
    public void testFindById() throws Exception {
        UserDO userDO = userMapper.findById(10);
        System.out.println(userDO);
    }
}

一对一查询

    @Select("select * from orders")
    @Results({
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "orderTime",column = "ordertime"),
            @Result(property = "total",column = "total"),
            @Result(property = "userDO",column = "uid",
                    javaType = UserDO.class, one = @One(select = "com.guslegend.mapper.UserMapper.findById"))
    })
    List<OrderVO> findAll() throws Exception;
    @Select("select * from user where id = #{id}")
    UserDO findById(Integer id) throws Exception;
    @Test
    public void test1() throws Exception {
        List<OrderVO> orderVOList = orderMapper.findAll();
        for (OrderVO orderVO : orderVOList){
            System.out.println(orderVO);
        }
    }

一对多查询

    @Select("select * from user")
    @Results({
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "username", column = "username"),
            @Result(property = "orders", column = "id",
                    javaType = List.class,
                    many = @Many(select = "com.guslegend.mapper.OrderMapper.findByUserId"))
    })
    List<UserVO> findAllUserAndOrder() throws Exception;
    @Select("select * from orders where uid = #{id}")
    List<OrderVO> findByUserId(Integer id) throws Exception;
    @Test
    public void test2() throws Exception {
        List<UserVO> userVOList = userMapper.findAllUserAndOrder();
        for (UserVO userVO : userVOList){
            System.out.println(userVO);
        }
    }

多对多查询

public interface RoleMapper {

    @Select("    select * from sys_role r , sys_user_role ur where  ur.userid =#{uid} and r.id = ur.roleid")
    List<RoleDO> findByUserId(int uid);
}
    @Select("select * from user")
    @Results({
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "username", column = "username"),
            @Result(property = "roles", column = "id",
                    javaType = List.class,
                    many = @Many(select = "com.guslegend.mapper.RoleMapper.findByUserId"))
    })
    List<UserVO> findAllUserAndRole2();
    @Test
    public void test3() throws Exception {
        List<UserVO> userVOList = userMapper.findAllUserAndRole2();
        for (UserVO userVO : userVOList){
            System.out.println(userVO);
        }
    }

Mybatis缓存

一级缓存

首先我们需要去打印一下sql日志方便我们去查看sql语句,所以要添加一个配置类log4j.properties

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout

我们查看控制台打印情况,发现只执行了一个sql。

然后我们只添加了一行sqlSession.clearCache(),就发现打印了两行sql语句。

通过以上实验,我们可以得出以下结论:

  1. 第一次发生查询语句的时候,我们先会从缓存中查询用户信息,没有查找到再从数据库中查询。
  2. 如果中间sqlSession去执行commit操作(增删改),则会清除sqlSession中的一级缓存,这样可以让缓存中存储的是最新的数据,避免脏读。

好了,接下来让我们带着一些列问题去阅读源码,来探究什么是一级缓存的原理。

  1. 一级缓存到底是什么?
  2. 一级缓存什么时候被创建?
  3. 一级缓存的工作流程又是怎么样的?

通过以上流程我们可以大概知道源码的阅读顺序是:

好,我们先在执行器Executor方法中查看发现

这里面最后一个environments是mybatis-config.xml中的标签。

我们追踪里面的query方法

二级缓存

一级缓存是基于sqlSession的,而二级缓存是基于mapper文件中的namespace的。

如何开启二级缓存:

和一级缓存默认开启不一样,二级缓存需要我们手动去开启。再全局配置文件sqlMapConfig.xml文件中加入如下代码:

<!--开启⼆级缓存-->
<settings>
 <setting name="cacheEnabled" value="true"/>
 </settings>

然后再UserMapeer下开启二级缓存

    <!--开启⼆级缓存-->
    <cache></cache>

开启二级缓存后,还需要将缓存pojo实现Serialiazble接口,为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一定只存在内存中,有可能存在硬盘中,如果我们要再去这个缓存的化,就需要反序列化了。所有mybatis中的pojo都要去实现Serializbale接口。

    @Test
    public void test() throws Exception {
        InputStream inputStream =Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();

        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);

        // 第一次sql
        UserDO u1 = userMapper1.findById(1);
        System.out.println(u1);
        sqlSession1.close();

        // 第二次sql
        UserDO u2 = userMapper2.findById(1);
        System.out.println(u2);
        sqlSession2.close();

    }

可以观察到两个不同的sqlSession,第一个关闭了,第二个查询依然不发出sql查询语句。

mybatis中还可以配置useCache和flushCache等配置项,useCache是用来设置是否禁用二级缓存的,在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发送sql去查询,默认是true,即该sql使用二级缓存。

<select id="selectUserByUserId" useCache="false" resultType="com.lagou.pojo.User"
parameterType="int">
 select * from user where id=#{id}
</select>

Redis整合二级缓存

为了实现在多台机器上都可以共享缓存,我们于是要采用分布式缓存,专门用来存储缓存数据的,这时候我们就想到了mybatis可以与redis结合。

添加mybatis-redis依赖

<dependency>
 <groupId>org.mybatis.caches</groupId>
 <artifactId>mybatis-redis</artifactId>
 <version>1.0.0-beta2</version>
</dependency>

更改UserMapper里面的配置

    <!--开启⼆级缓存-->
    <cache type="org.mybatis.caches.redis.RedisCache"></cache>

    <select id="findAll" resultType="UserDO" useCache="true">
        select * from user
    </select>

添加redis配置文件

redis.host=localhost
redis.port=6379
redis.connectionTimeout=5000
redis.password=123456
redis.database=1

Mybatis插件

  1. StatementHandler (prepare, parameterize, batch, update, query)
    我们看到了可以拦截Executor接⼝的部分⽅法,⽐如update,query,commit,rollback等⽅法,还有其他接⼝
    的⼀些⽅法等。
    总体概括为:
  2. 拦截执⾏器的⽅法
  3. 拦截参数的处理
  4. 拦截结果集的处理
  5. 拦截Sql语法构建的处理

拦截器示例:

package com.guslegend.interceptor;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;

import java.util.Properties;

@Intercepts({@Signature(
        type = Executor.class,
        method = "update",
        args = {MappedStatement.class, Object.class}
)})
public class MyInterceptor implements Interceptor {

    @Override
    public Object plugin(Object target) {
        //创建target对象的代理对象,⽬的是将当前拦截器加⼊到该对象中
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        //属性设置
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 拦截方法,具体业务逻辑编写的位置
        System.out.println("拦截方法");
        return invocation.proceed();
    }
}

注入到spring容器中

    @Bean
    public MyInterceptor myInterceptor() {
        return new MyInterceptor();
    }

本系统旨在构建一套面向高等院校的综合性教务管理平台,涵盖学生、教师及教务处三个核心角色的业务需求。系统设计着重于实现教学流程的规范化与数据处理的自动化,以提升日常教学管理工作的效率与准确性。 在面向学生的功能模块中,系统提供了课程选修服务,学生可依据培养方案选择相应课程,并生成个人专属的课表。成绩查询功能支持学生查阅个人各科目成绩,同时系统可自动计算并展示该课程的全班最高分、平均分、最低分以及学生在班级内的成绩排名。 教师端功能主要围绕课程与成绩管理展开。教师可发起课程设置申请,提交包括课程编码、课程名称、学分学时、课程概述在内的新课程信息,亦可对已开设课程的信息进行更新或撤销。在课程管理方面,教师具备录入所授课程期末考试成绩的权限,并可导出选修该课程的学生名单。 教务处作为管理中枢,拥有课程审批与教学统筹两大核心职能。课程设置审批模块负责处理教师提交的课程申请,管理员可根据教学计划与资源情况进行审核批复。教学安排模块则负责全局管控,包括管理所有学生的选课最终结果、生成包含学号、姓名、课程及成绩的正式成绩单,并能基于选课与成绩数据,统计各门课程的实际选课人数、最高分、最低分、平均分以及成绩合格的学生数量。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值