Mybatis的回顾与高级应用

一、基础回顾

mybatis(一)
mybatis(二)
mybatis(三)

二、高级应用

2.1 二级缓存整合redis
2.1.1 使用的redis的 因果
  • 为什么要整合 用redis 整合二级缓存?

如果 你是 单服务器工作,可以使用mybatis自带的二级缓存。
但是 现在大多数是 ,分布式的 服务。服务器之间不能 完成 二级缓存的通信。这时候就需要使用到redis 来为我们完成 分布式缓存。

举个栗子

  • 假设现在有两个服务器1和2,用户访问的时候访问了 1服务器,查询后的缓 存就会放在1服务器上,假设现在有个用户访问的是2服务器,那么他在2服务器上就无法获取刚刚那个 缓存。

为了解决这个问题,就得找一个分布式的缓存,专门用来存储缓存数据的,这样不同的服务器要缓存数
据都往它那里存,取缓存数据也从它那里取。

如下图。

在这里插入图片描述

2.1.2 使用的redis的具体实现
  • mybatis提供了一个eache接口,如果要实现自己的缓存逻辑,实现cache接口开发即可。
  • mybatis提供了一个针对cache接口的redis实现类,该类存在mybatis-redis。

实现:

  1. pom文件
<dependency> 
	<groupId>org.mybatis.caches</groupId> 
	<artifactId>mybatis-redis</artifactId> 
	<version>1.0.0-beta2</version> 
</dependency>

2.配置文件

<?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.lagou.mapper.IUserMapper"> 
 <cache type="org.mybatis.caches.redis.RedisCache" /> 
 <select id="findAll" resultType="com.lagou.pojo.User" useCache="true"> 
		select * from user 
 </select>

3.redis.properties


redis.host=localhost 
redis.port=6379 
redis.connectionTimeout=5000 
redis.password= redis.database=0

  1. 测试类

    @Test
    public void SecondLevelCache() {
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        SqlSession sqlSession3 = sqlSessionFactory.openSession();
        IUserMapper mapper1 = sqlSession1.getMapper(IUserMapper.class);
        lUserMapper mapper2 = sqlSession2.getMapper(lUserMapper.class);
        lUserMapper mapper3 = sqlSession3.getMapper(IUserMapper.class);
        User user1 = mapper1.findUserById(1);
        sqlSession1.close();
        //清空一级缓存 
        User user = new User();
        user.setId(1);
        user.setUsername("lisi");
        mapper3.updateUser(user);
        sqlSession3.commit();
        User user2 = mapper2.findUserById(1);
        System.out.println(user1 == user2); 
    }

2.1.3 使用的redis的源码的说明
2.2 插件的使用
2.2.1 插件简介

一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展。这样的好处是显而易见
的,一是增加了框架的灵活性。二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工
作。以MyBatis为例,我们可基于MyBati s插件机制实现分页、分表,监控等功能。由于插件和业务 无
关,业务也无法感知插件的存在。因此可以无感植入插件,在无形中增强功能.

2.2.2 Mybatis插件简介

Mybati s作为一个应用广泛的优秀的ORM开源框架,这个框架具有强大的灵活性,在四大组件
(Executor、StatementHandler、ParameterHandler、ResultSetHandler)处提供了简单易用的插 件扩
展机制。Mybatis对持久层的操作就是借助于四大核心对象。MyBatis支持用插件对四大核心对象进 行
拦截,对mybatis来说插件就是拦截器,用来增强核心对象的功能,增强功能本质上是借助于底层的 动
态代理实现的,换句话说,MyBatis中的四大对象都是代理对象.
在这里插入图片描述
MyBatis所允许拦截的方法如下:

  1. 执行器Executor (update、query、commit、rollback等方法);
  2. SQL语法构建器StatementHandler (prepare、parameterize、batch、updates query等方 法);
  3. 参数处理器ParameterHandler (getParameterObject、setParameters方法);
  4. 结果集处理器ResultSetHandler (handleResultSets、handleOutputParameters等方法);
2.2.3 实现一个简单的自定义Mybatis插件

SqlMapConfig.xml


    <plugins>
        <plugin interceptor="com.lagou.plugin.MyPlugin">
            <property name="name" value="Tom"/>
        </plugin>
    </plugins>


Usermapper.xml

<?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.lagou.mapper.UserMapper">

    <select id="selectUsers" resultType="com.lagou.pojo.User">
        SELECT id,username FROM user
     </select>


</mapper>

MyPlugin


package com.lagou.plugin;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;

import java.sql.Connection;
import java.util.Properties;


//拦截器的设置
@Intercepts({  //这里这个大括号,也就是说 这里可以定义对个@Signature 对 对个地方进行拦截,都用这个拦截器。
        @Signature(type = StatementHandler.class,   // 指定拦截的那个接口
                method = "prepare",     // 指定  要拦截的接口的 中要拦截的方法
                args = {Connection.class, Integer.class})  // 指定  要拦截的接口的 中要拦截的方法 中的参数,按顺序,不要多,也不要少。如果方法重载,通过这个 来确定你要执行的方法。

})
public class MyPlugin implements Interceptor {

    /**
     * 拦截方法,只要别拦截的目标对象的目标方法别执行时,每次都会执行intercept方法
     *
     * @param invocation
     * @return
     * @throws Throwable
     */

    @Override
    public Object intercept(Invocation invocation) throws Throwable {

        System.out.println("对方法进行了增强");
        return invocation.proceed();  //执行原方法
    }

    /**
     * 主要为了把当前的拦截器生成代理存到拦截器链中
     *
     * @param
     * @return
     */
    @Override
    public Object plugin(Object target) {

        System.out.println("将要包装的目标对象:" + target);
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

        System.out.println("插件配置的初始化参数:" + properties);
    }
}


PluginTest


import com.lagou.mapper.UserMapper;
import com.lagou.pojo.User;
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.Test;

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

public class PluginTest {


    @Test
    public void test() throws IOException {

        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");

        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);

        SqlSession sqlSession = build.openSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);


        List<User> users = mapper.selectUsers();

        users.forEach(System.out::println);


    }

}


package com.lagou.pojo;

public class User {

    private int id;
    private String username;

    public User(int id, String username) {
        this.id = id;
        this.username = username;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                '}';
    }
}


UserMapper


package com.lagou.mapper;

import com.lagou.pojo.User;

import java.util.List;

public interface UserMapper {

    List<User> selectUsers();
}


2.2.4 pageHelper分页插件

MyBati s可以使用第三方的插件来对功能进行扩展,分页助手PageHelper是将分页的复杂操作进行封
装,使用简单的方式即可获得分页的相关数据

开发步骤:
① 导入通用PageHelper的坐标
② 在mybatis核心配置文件中配置PageHelper插件
③ 测试分页数据获取

  1. 导入通用PageHelper坐标

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>3.7.5</version>
        </dependency>
        <dependency>
            <groupId>com.github.jsqlparser</groupId>
            <artifactId>jsqlparser</artifactId>
            <version>0.9.1</version>
        </dependency>


  1. 在mybatis核心配置文件中配置PageHelper插件\

<!--注意:分页助手的插件 配置在通用馆mapper之前*-->* 
<plugin interceptor="com.github.pagehelper.PageHelper"> 
<!—指定方言 > 
<property name="dialect" value="mysql"/> 
</plugin>

  1. 测试分页代码实现

    @Test
    public void testPageHelper() {
	//设置分页参数 
        PageHelper.startPage(1, 2);
        List<User> select = userMapper2.select(null);
        for (User user : select) {
            System.out.println(user);
        }
    }
}

获得分页相关的其他参数


//其他分页的数据 
PageInfo<User> pageInfo = new PageInfo<User>(select); 
System.out.println("总条数:"+pageInfo.getTotal());
System.out.println("总页数:"+pageInfo. getPages ());
System.out.println("当前页:"+pageInfo. getPageNum()); 
System.out.println("每页显万长度:"+pageInfo.getPageSize()); 
System.out.println("是否第一页:"+pageInfo.isIsFirstPage()); 
System.out.println("是否最后一页:"+pageInfo.isIsLastPage());


  • 开发步骤:
    导入通用PageHelper的坐标
    在mybatis核心配置文件中配置PageHelper插件
    测试分页数据获取
2.2.5 通用 mapper

什么是通用Mapper
通用Mapper就是为了解决单表增删改查,基于Mybatis的插件机制。开发人员不需要编写SQL,不需要
在DAO中增加方法,只要写好实体类,就能支持相应的增删改查方法

如何使用

  1. 首先在maven项目,在pom.xml中引入mapper的依赖

<dependency> 
	<groupId>tk.mybatis</groupId> 
	<artifactId>mapper</artifactId> 
	<version>3.1.2</version> 
</dependency>

  1. Mybatis配置文件中完成配置

<plugins> 
	<!--分页插件:如果有分页插件,要排在通用mapper之前--> 
	<plugin interceptor="com.github.pagehelper.PageHelper"> 
	<property name="dialect" value="mysql"/> 
	</plugin> 
	<plugin interceptor="tk.mybatis.mapper.mapperhelper.MapperInterceptor"> <!-- 通用Mapper接口,多个通用接口用逗号隔开 --> 
	<property name="mappers" value="tk.mybatis.mapper.common.Mapper"/> 
	</plugin>
 </plugins>

  1. 实体类设置主键

@Table(name = "t_user") 
public class User { 
	@Id @GeneratedValue(strategy = GenerationType.IDENTITY) 
	private Integer id; 
	private String username; 
}

  1. 定义通用mapper
import com.lagou.domain.User; 
import tk.mybatis.mapper.common.Mapper; 
public interface UserMapper extends Mapper<User> { 
}

  1. 测试
public class UserTest {
    @Test
    public void test1() throws IOException {
        Inputstream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = build.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setId(4);
        
        //(1)mapper基础接口 //select 接口

        User user1 = userMapper.selectOne(user);
        //根据实体中的属性进行查询,只能有 — 个返回值
        List<User> users = userMapper.select(null);
        //查询全部结果 
        userMapper.selectByPrimaryKey(1);
        //根据主键字段进行查询,方法参数必须包含完 整 的主键属性,查询条件使用等号 
        userMapper.selectCount(user);
        //根据实体中的属性查询总数,查询条件使用等号 
        // insert 接口 
        int insert = userMapper.insert(user);
        //保存一个实体,null值也会保存,不会使 用数据库默认值 
        int i = userMapper.insertSelective(user);
        //保存实体,null的属性不会保存, 会 使用数据库默认值 
        // update 接口 
        int i1 = userMapper.updateByPrimaryKey(user);
        //根据主键更新实体全部字段, null值会被更新 
        // delete 接口 
        int delete = userMapper.delete(user);
        //根据实体属性作为条件进行删除,查询条件 使用等号 
        userMapper.deleteByPrimaryKey(1);
        //根据主键字段进行删除,方法参数必须包含完 整 的主键属性
        
        // (2)example方法 
        Example example = new Example(User.class);
        example.createCriteria().andEqualTo("id", 1);
        example.createCriteria().andLike("val", "1");

        //自定义查询 
        List<User> users1 = userMapper.selectByExample(example);
    }
}



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值