Mybatis学习笔记第四天

11.动态SQL

什么是动态SQL?

根据不同的条件生成不同的sql语句

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

if
choose (when, otherwise)
trim (where, set)
foreach

1.搭建环境

CREATE TABLE `blog`(
  `id` VARCHAR(50) NOT NULL COMMENT '博客id',
  `title` VARCHAR(100) NOT NULL COMMENT '博客标题',
  `author` VARCHAR(30) NOT NULL COMMENT '博客作者',
  `create_time` DATETIME NOT NULL COMMENT '创建时间',
  `views` INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8

2.创建一个基础工程

1.导包

2.编写配置文件

3.编写实体类

package com.cjp.pojo;

import lombok.Data;

import java.util.Date;

@Data
public class Blog {
    private int id;
    private String title;
    private String author;
    private Date createTime;
    private int views;
}

4.编写实体类对应的Mapper接口和Mapper.xml文件

3.IF、where

1.编写Mapper接口:

    //查询数据
    List<Blog> queryBlogIf(Map map);

2.编写Mapper.xml

	<select id="queryBlogIf" parameterType="map" resultType="Blog">
        select * from blog
        <where>
        <if test="title!=null">
            title=#{title}
        </if>
        <if test="author!=null">
            and author=#{author}
        </if>
        </where>
    </select>

3.测试

	@Test
    public void test1(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("author","cjp");
        map.put("title","java入门");
        List<Blog> blogs = mapper.queryBlogIf(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

4.choose (when, otherwise)

1.编写Mapper接口

List<Blog> queryBlogChoose(Map mp);

2.编写Mapper.xml

	<select id="queryBlogChoose" parameterType="map" resultType="Blog">
        select * from blog
        <where>
            <choose>
                <when test="title!=null">
                    title=#{title}
                </when>
                <when test="author!=null">
                    and author=#{author}
                </when>
                <otherwise>
                    and views=#{views}
                </otherwise>
            </choose>
        </where>
    </select>

3.测试

	@Test
    public void test2(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("author","cjp");
        map.put("title","java入门");
        map.put("views",100);
        List<Blog> blogs = mapper.queryBlogChoose(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

5、set

1.接口

int updateBlog(Map map);

2.Mapper.xml

	<update id="updateBlog" parameterType="map" >
        update blog
        <set>
            <if test="title!=null">
                title=#{title},
            </if>
            <if test="author!=null">
                author=#{author}
            </if>
        </set>
        where id = #{id}
    </update>

3.测试

 	@Test
    public void test2(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap<String, Object> map = new HashMap<>();
        map.put("title","文创");
        map.put("id","2206835f5ce4417e9156eed632785cdc");
        mapper.updateBlog(map);
        sqlSession.close();
    }

6.SQL片段

将通用的SQL语句提取出来,提高SQL语句的可复用性

	<update id="updateBlog" parameterType="map" >
        update blog
        <set>
            <include refid="if"></include>
        </set>
        where id = #{id}
    </update>
    <sql id="if">
        <if test="title!=null">
            title=#{title},
        </if>
        <if test="author!=null">
            author=#{author}
        </if>
    </sql>

注意:

  • 最好基于单表来定义SQL片段
  • 不要存在where标签

7.foreach

1.接口

List<Blog> queryBlogForEach(Map map);

2.Mapper.xml

	<select id="queryBlogForEach" parameterType="map" resultType="Blog">
        select * from blog
        <where>
            <foreach collection="ids" item="id" open="and (" close=")" separator="or">
                id=#{id}
            </foreach>
        </where>
    </select>

3.测试

	@Test
    public void test3() {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        ArrayList<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
        map.put("ids", ids);
        List<Blog> blogs = mapper.queryBlogForEach(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

12、缓存

1、一级缓存
  • 一级缓存也叫本地缓存:sqlSession
    • 与数据库同一次会话期间查询到的数据会放在本地缓存中
    • 以后如果需要获取相同的数据,直接从缓存中拿,无需再次查询数据库;

测试步骤:

1.开启日志

2.测试在一个Session中查询两次相同记录

 @Test
    public void test(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserByID(1002);
        System.out.println(user);


        System.out.println("=======================");
        User user2 = mapper.getUserByID(1002);
        System.out.println(user2);
        System.out.println(user==user2);
        sqlSession.close();

    }

3.查看日志输出

Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 1415157681.
==>  Preparing: select * from user where id =?; 
==> Parameters: 1002(Integer)
<==    Columns: id, name, pwd
<==        Row: 1002, 张三, 1234
<==      Total: 1
User(id=1002, name=张三, pwd=1234)
=======================
User(id=1002, name=张三, pwd=1234)
true
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@545997b1]
Returned connection 1415157681 to pool.

缓存失效:

1.查询的不同的东西

2.增删改可能会改变原来的数据,所以必定会刷新缓存!

@Test
    public void test(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserByID(1002);
        System.out.println(user);
        
        mapper.update(new User(1001,"张朝阳","202020" ));
        
        System.out.println("=======================");
        User user2 = mapper.getUserByID(1002);
        System.out.println(user2);
        System.out.println(user==user2);
        sqlSession.close();

    }

3.查询不同的Mapper.xml

4.手动清理缓存

sqlSession.clearCache();//手动清理缓存

小结:一级缓存是默认开启的,只在一次SQLSession 中有效 。

2、二级缓存

步骤:

1、开启全局缓存(Mybits默认开启全局缓存)

<setting name="cacheEnabled" value="true"/>

2.在要使用二级缓存的Mapper.xml中开启缓存

<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>

也可以自定义参数

3.测试

@Test
    public void test(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        SqlSession sqlSession2 = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        UserMapper mapper2= sqlSession2.getMapper(UserMapper.class);
        User user = mapper.getUserByID(1002);
        System.out.println(user);
        sqlSession.close();

        System.out.println("======================");

        User user2 = mapper2.getUserByID(1002);
        System.out.println(user2);
        sqlSession2.close();
    }

**问题:**我们需要将实体类序列化,否则就会报错:

Cause: java.io.NotSerializableException: com.cjp.pojo.User

所有的数据都会先放在一级缓存中,只有当会话提交或者关闭的时候才会提交到二级缓存中 !

缓存顺序

查询数据,先看二级缓存中有没有,没有再看一级缓存,再没有就查询数据库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CjIZkBcZ-1652094332543)(D:\Desktop\学习笔记\图片\image-20220509164642026.png)]

自定义缓存-ehcache

使用步骤:

1.导包

	<dependency>
        <groupId>org.mybatis.caches</groupId>
        <artifactId>mybatis-ehcache</artifactId>
        <version>1.1.0</version>
    </dependency>

2.使用导入的缓存

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

3.新建配置文件ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">

    <diskStore path="./tmpdir/Tmp_EhCache"/>

    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="259200"
            memoryStoreEvictionPolicy="LRU"/>

    <cache
            name="cloud_user"
            eternal="false"
            maxElementsInMemory="5000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="1800"
            memoryStoreEvictionPolicy="LRU"/>
</ehcache>

除了上述自定义缓存的方式,你也可以通过实现你自己的缓存,或为其他第三方缓存方案创建适配器,来完全覆盖缓存行为。

<cache type="com.domain.something.MyCustomCache"/>

这个示例展示了如何使用一个自定义的缓存实现。type 属性指定的类必须实现 org.apache.ibatis.cache.Cache 接口,且提供一个接受 String 参数作为 id 的构造器。 这个接口是 MyBatis 框架中许多复杂的接口之一,但是行为却非常简单。

public interface Cache {
  String getId();
  int getSize();
  void putObject(Object key, Object value);
  Object getObject(Object key);
  boolean hasKey(Object key);
  Object removeObject(Object key);
  void clear();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值