MyBatis(五)动态sql、分页插件、缓存

一、xml中重要的标签

1.1、where标签

查询条件实体类

public class QueryTeamVO {

    private String name;

    private Date beginTime;

    private Date endTime;

    private String location;

    public QueryTeamVO() {
    }

    public QueryTeamVO(String name, Date beginTime, Date endTime, String location) {
        this.name = name;
        this.beginTime = beginTime;
        this.endTime = endTime;
        this.location = location;
    }

    @Override
    public String toString() {
        return "QueryTeamVO{" +
                "name='" + name + '\'' +
                ", beginTime=" + beginTime +
                ", endTime=" + endTime +
                ", location='" + location + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBeginTime() {
        return beginTime;
    }

    public void setBeginTime(Date beginTime) {
        this.beginTime = beginTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }
} 

TeamMapper.java中添加接口方法

    List<Team> queryByVO(QueryTeamVO vo);

TeamMapper.xml添加映射方法

<select id="queryByVO" parameterType="QueryTeamVO" resultMap="baseResultMap">
        select * from team
        <where>
            <!--第一个判断条件中 and可写可不写-->
            <if test="name!=null">
                and teamName like CONCAT('%',#{name},'%')
            </if>
            <if test="beginTime!=null">
                and createTime>= #{beginTime}
            </if>
            <if test="endTime!=null">
                and createTime &lt;= #{endTime}
            </if>
            <if test="location!=null">
                and location = #{location}
            </if>
        </where>
    </select>

添加测试类:

public class DynamicSqlTest {

    private TeamMapper mapper = MybatisUtil.getSqlSession().getMapper(TeamMapper.class);

    @Test
    public void test1() {
        QueryTeamVO vo=new QueryTeamVO();
        vo.setName("士");
        vo.setEndTime(new Date());
        List<Team> teams = mapper.queryByVO(vo);
        teams.forEach(team -> {
            System.out.println(team);
        });
    } 
}

测试结果

在这里插入图片描述

查询sql的条件中与传入参数对应

1.2、set标签

添加Mapper接口方法:

    Integer update1(Team team);

添加xml映射:

<update id="update1" parameterType="team">
        update team
        <set>
            <if test="teamName!=null">
                teamName=#{teamName},
            </if>
            <if test="location!=null">
                location=#{location},
            </if>
            <if test="createTime!=null">
                createTime=#{createTime}
            </if>
        </set>
        where teamId=#{teamId}
    </update>

添加测试方法:

 @Test
    public void test2(){
        Team team = mapper.queryById(1117);
        team.setTeamName("hotFire");
        team.setCreateTime(new Date());
        team.setLocation(null);
        Integer num = mapper.update1(team);
        System.out.println("影响结果数量:"+num);
    }

1.3、forEach标签

1.3.1、批量添加

接口添加方法:

    void addList(List<Team> teamList);

mapper添加映射方法

    <insert id="addList" parameterType="arrayList">
        insert into team(teamName,location) values
        <foreach collection="list" item="t" separator=",">
            (#{t.teamName},#{t.location})
        </foreach>
    </insert>

添加测试方法

    @Test
    public void test3(){
        List<Team> list=new ArrayList<>();
        for (int i=0;i<3;i++){
            Team team=new Team();
            team.setTeamName("jk"+i);
            team.setLocation("address"+i);
            team.setCreateTime(new Date());
            list.add(team);
        }
        mapper.addList(list);
        MybatisUtil.getSqlSession().commit();
    }

1.3.2、批量删除

接口添加方法:

    void delList(List<Integer> list);

mapper映射方法:

    <delete id="delList" parameterType="arrayList">
        delete from team where teamId in
        <!--collection=要遍历的集合,参数直接写集合类型
            item=遍历集合中的每一个元素
            separator=遍历集合中每个元素用,分割
            open=开始包裹元素,close=结束包裹元素-->
        <foreach collection="list" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </delete>

添加测试方法:

 @Test
    public void test4(){
        List<Integer> list=new ArrayList<>();
        list.add(1116);
        list.add(1117);
        mapper.delList(list);
        MybatisUtil.getSqlSession().commit();
    }

二、分页插件

2.1、添加jar包

    <!--分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.3.0</version>
        </dependency>

2.2、添加全局配置

  <!-- 引入 pageHelper插件 --> <!--注意这里要写成PageInterceptor, 5.0之前的版本都是写PageHelper, 5.0之后要换成PageInterceptor-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!--reasonable:分页合理化参数,默认值为false,直接根据参数进行查询。 当该参数设置为 true 时,pageNum<=0 时会查询第一页,
            pageNum>pages(超过总数时),会查询最后一页。 方言可以省略,会根据连接数据的参数url自动推断-->
            <!--<property name="reasonable" value="true"/>-->
        </plugin>
    </plugins>

2.3、添加测试方法

 @Test
    public void test5(){
        // PageHelper.startPage 必须紧邻查询语句,而且只对第一条查询语句生效 
        PageHelper.startPage(2,5);
        // 查询语句结尾不能有;
        List<Team> teams = mapper.queryAll();
        teams.forEach(team -> {
            System.out.println(team);
        });
        PageInfo<Team> pageInfo=new PageInfo<>(teams);
        System.out.println("分页信息如下:");
        System.out.println("当前页数:"+pageInfo.getPageNum());
        System.out.println("总页数:"+pageInfo.getPages());
        System.out.println("前一页:"+pageInfo.getPrePage());
        System.out.println("后一页:"+pageInfo.getNextPage());
    }

三、mybatis缓存

3.1、缓存的作用

缓存是一般的ORM框架都会提供的功能,目的是提高查询效率和减少数据库压力。将经常查询的数据存在缓存中,用户查询数据时不需要再从磁盘上读取,直接从缓存中读取,提高查询效率,解决高并发问题。

在这里插入图片描述

3.2、一级缓存

sqlsession缓存,自动开启。在操作数据库时需要构造sqlsession对象,该对象拥有一个数据结构HashMap用户缓存数据。不同的sqlSession之间的HashMap互不影响。

一级缓存的作用域是同一个sqlSession,在同一个sqlSession执行两次的sql语句,第一次执行完毕就会将查询的结果写入到缓存中,第二次从缓存中读取而不是从数据库中查询,提高查询效率。

当一个sqlSession结束后,sqlsession中的一级缓存也就不存在了。

Mybatis默认开启一级缓存,存在内存中不能被关闭,可以调用clearCache()来清空本地缓存,或者改变缓存的作用域。

3.2.1、一级缓存分析

工作原理

在这里插入图片描述

测试类:

public class TestCache {

    private SqlSession sqlSession= MybatisUtil.getSqlSession();

    @Test
    public void test1(){
        TeamMapper teamMapper = sqlSession.getMapper(TeamMapper.class);
        Team team = teamMapper.queryById(1001);
        System.out.println(team);
        Team team1 = teamMapper.queryById(1001);
        System.out.println(team1);
        MybatisUtil.closeSqlSession();//关闭连接,清空缓存

        sqlSession= MybatisUtil.getSqlSession();
        teamMapper=sqlSession.getMapper(TeamMapper.class);//再次获取连接,此时缓存为空
        Team team3 = teamMapper.queryById(1001);
        System.out.println(team3);
        teamMapper.delete(1131);
        MybatisUtil.getSqlSession().commit();//提交之后缓存清空

        Team team4 = teamMapper.queryById(1001);
        System.out.println(team4);
    } 
}

清空缓存方式:

  1. session.clearCache();
  2. execute update();
  3. session.close();
  4. xml配置 flushCache=true
  5. rollback;
  6. commit;

3.2、二级缓存

Mapper级别的缓存。多个SqlSession共同去操作一个Mapper的sql语句,多个SqlSession可以共用二级缓存。

二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace。

不同的sqlSession两次执行相同的namespace下的sql语句参数相同即执行相同的sql语句,第一次执行会将执行结果写入缓存,第二次执行直接从内存中获取结果,提高查询效率。

Mybatis默认没有开启二级缓存,需要在setting全局设置中配置开启二级缓存。

二级缓存原理图:

在这里插入图片描述

3.2.1、启用二级缓存步骤

二级缓存是mapper级别,默认不启用。

1、Mybatis的全局配置文件中开启二级缓存

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

2、在需要二级缓存的mapper中添加缓存标志

<mapper namespace="com.jsonliu.test.mapper.TeamMapper">
    <cache></cache>
    ...
</mapper>

3、实体类必须实现Serializable接口

public class Team implements Serializable {
    ...
}

4、测试二级缓存

如果两个Session不是同一个Factory获取,那么二级缓存不起作用。

 @Test
    public void test2(){
        SqlSession sqlSession1 = MybatisUtil.getSqlSession();
        TeamMapper mapper1 = sqlSession1.getMapper(TeamMapper.class);
        Team team1 = mapper1.queryById(1001);
        System.out.println(team1);
        MybatisUtil.closeSqlSession();

        SqlSession sqlSession2 = MybatisUtil.getSqlSession();
        TeamMapper mapper2 = sqlSession2.getMapper(TeamMapper.class);
        Team team2 = mapper2.queryById(1001);
        System.out.println(team2);
        MybatisUtil.closeSqlSession();

        SqlSession sqlSession3= MybatisUtil.getSqlSession();
        TeamMapper mapper3 = sqlSession3.getMapper(TeamMapper.class);
        Integer delete = mapper3.delete(1031);
        System.out.println(delete);
        MybatisUtil.closeSqlSession();

        SqlSession sqlSession4 = MybatisUtil.getSqlSession();
        TeamMapper mapper4 = sqlSession4.getMapper(TeamMapper.class);
        Team team4 = mapper4.queryById(1001);
        System.out.println(team4);
        MybatisUtil.closeSqlSession(); 
    }

3.2.2、禁用二级缓存

对于变化比较频繁的sql,可以禁用二级缓存。
在开始了二级缓存的XML中对应的statement中设置useCache=false禁用当前Select语句的二级缓存,意味着该SQL语句每次只需都去查询数据库,不会查询缓存。
useCache默认值是true。对于一些很重要的数据尽不放在二级缓存中。

3.2.3、缓存的属性配置

<cache> 
    <property name="eviction" value="LRU"/><!--回收策略为LRU--> 
    <property name="flushInterval" value="60000"/><!--自动刷新时间间隔为60S--> 
    <property name="size" value="1024"/><!--最多缓存1024个引用对象-->
    <property name="readOnly" value="true"/><!--只读--> 
</cache>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笑谈子云亭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值