MyBatis快速入门(三)(隔壁王大爷都学会了!)

本文介绍了MyBatis中的动态SQL,包括`<if>`、`<where>`、`<set>`、`<foreach>`、`<trim>`标签的使用,展示了如何根据条件动态拼接SQL。此外,还讲解了MyBatis的一级缓存和二级缓存机制,解释了缓存在提高程序效率中的作用,并给出了启用和使用缓存的示例。

一、动态SQL【重点


MyBatis的映射文件中支持在基础SQL上添加一些逻辑操作,并动态拼接成完整的SQL之后再执行,以达到SQL复用、简化编程的效果。

首先我们建一个简单的user表

1.1 < sql >

dao层接口中的方法为:
public List<User> getUser();

对应的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.qwz.dao.UserDao">
    <resultMap id="userMap" type="com.qwz.entity.User">
        <id property="id" column="id"></id>
        <result property="username" column="username"></result>
        <result property="password" column="password"></result>
    </resultMap>
<!--    配置查询所有-->
    <sql id="baseSql">
        select *
    </sql>
    <select id="getUser" resultMap="userMap">
        <!-- 引入sql片段 -->
        <include refid="baseSql"></include>
        from user
    </select>

</mapper>

1.2 < if >

public User getUser(User user);
<sql id="baseSql">
        select *
    </sql>
    <select id="getUser" resultMap="userMap">
        <!-- 引入sql片段 -->
        <include refid="baseSql"></include>
        from user where
        <if test="username!=null">
            username = #{username}
        </if>

        <if test="username != null and password != null">
            and
        </if>

        <if test="password!=null">
            password = #{password}
        </if>
    </select>

1.3 < where >

public User getUser(User user);
 <sql id="baseSql">
        select *
    </sql>
    <select id="getUser" resultMap="userMap">
        <!-- 引入sql片段 -->
        <include refid="baseSql"></include>
        from user <where>
        <if test="username!=null">
            username = #{username}
        </if>

        <if test="username != null and password != null">
            and
        </if>

        <if test="password!=null">
            password = #{password}
        </if>
    </where>
    </select>

1.4 < set >

public int update(User user);
 <update id="update">
        update user
        <set>
        username = #{username},
        password = #{password}
        </set>
        <where>
            id = #{id}
        </where>
    </update>

可以看到数据修改成功了         当然我们可以在sql语句里插入if 判断 

1.5 < trim >

< trim prefix="" suffix="" prefixOverrides="" suffixOverrides="" >代替< where > 、< set >

<select id="getUser" resultType="com.qwz.entity.User">
    <include refid="BaseSql"></include>
    FROM t_user
    <trim prefix="WHERE" prefixOverrides="AND|OR"> <!-- 增加WHERE前缀,自动忽略前缀 -->
        <if test="name!=null">
            and name=#{name}
        </if>
        <if test="password!=null">
            and password=#{password}
        </if>
    </trim>
</select>
<update id="update">
    update t_user
    <trim prefix="SET" suffixOverrides=","> <!-- 增加SET前缀,自动忽略后缀 -->
        <if test="name!=null">
            name=#{name},
        </if>
        <if test="password!=null">
            password=#{password},
        </if>
    </trim>
    <where>
        <if test="id!=null">
            id=#{id}
        </if>
    </where>
</update>

1.6 < foreach >

通过多个id查询 

public List<User> getUserByIds(List<Integer> ids);
 <sql id="baseSql">
        select *
    </sql>
 <select id="getUserByIds" resultMap="userMap">
        <include refid="baseSql"></include>
        from user where id in
        <foreach collection="list" open="(" close=")" separator="," item="id" index="0">
            #{id}
        </foreach>
    </select>

测试类为

 @org.junit.Test
    public void test() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = build.openSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        arrayList.add(5);
        arrayList.add(7);
        List<User> userByIds = mapper.getUserByIds(arrayList);
        sqlSession.commit();
        for (User userById : userByIds) {
            System.out.println(userById);
        }
        sqlSession.close();
        inputStream.close();
    }

结果为

参数描述取值
collection容器类型list、array、map
open起始符(
close结束符)
separator分隔符,
index下标号从0开始,依次递增
item当前项任意名称(循环中通过 #{任意名称} 表达式访问)

二、缓存(Cache)【重点


内存中的一块存储空间,服务于某个应用程序,旨在将频繁读取的数据临时保存在内存中,便于二次快速访问。

无缓存:用户在访问相同数据时,需要发起多次对数据库的直接访问,导致产生大量IO、读写硬盘的操作,效率低下

有缓存:首次访问时,查询数据库,将数据存储到缓存中;再次访问时,直接访问缓存,减少IO、硬盘读写次数、提高效率

2.1 一级缓存(注意!所建立的实体类一定要实现序列化)

SqlSession级别的缓存,同一个SqlSession的发起多次同构查询,会将数据保存在一级缓存中。

import com.qwz.dao.UserDao;
import com.qwz.entity.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 java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class Test {
    @org.junit.Test
    public void test() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = build.openSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        User user2 = new User();
        user2.setId(1);
//        默认一级缓存
        List<User> user = mapper.getUser(user2);
//        sqlSession.clearCache(); 清除缓存
        List<User> user1 = mapper.getUser(user2);

        sqlSession.close();
        inputStream.close();
    }
}

我们可以加入log4j的日志文件依赖

先把 sqlSession.clearCache(); 清除缓存注释掉

然后调用两次getUser的方法 假设没有缓存的存在的话 我们这时候就该再控制台看到执

行了两次sql语句 然而结果如下

可以看到只执行了一次sql语句,所以当我们第二次掉方法获取结果的时候,因为我们传入的参数都是一样的,所以默认从缓存中取出数据了

我么可以再将第一次调用这个方法后 把缓存清一下 再看一下结果比对一下

可以看到这时候就是执行了两次sql语句,所以有缓存的时候我们程序的执行效率肯定比没有缓存的快啦! 

2.2 二级缓存

SqlSessionFactory级别的缓存,同一个SqlSessionFactory构建的SqlSession发起的多次同构查询,会将数据保存在二级缓存中。

2.2.1 开启全局缓存

< settings >是MyBatis中极为重要的调整设置,他们会改变MyBatis的运行行为,其他详细配置可参考官方文档。

<configuration>
    <properties .../>
    
    <!-- 注意书写位置 -->
    <settings>
        <setting name="cacheEnabled" value="true"/> <!-- mybaits-config.xml中开启全局缓存(默认开启) -->
    </settings>
  
    <typeAliases></typeAliases>
</configuration>

2.2.2 指定Mapper缓存

在指定的mapper中 加入

<cache></cache>

 

import com.qwz.dao.UserDao;
import com.qwz.entity.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 java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class Test {
    @org.junit.Test
    public void test() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(inputStream);


        //生产一级缓存
        SqlSession sqlSession1 = build.openSession();
        SqlSession sqlSession2 = build.openSession();
        SqlSession sqlSession3 = build.openSession();


        UserDao mapper1 = sqlSession1.getMapper(UserDao.class);
        List<User> user1 = mapper1.getUser(1);
        System.out.println(user1);
        //关闭一级缓存
        sqlSession1.close();

        //另一个缓存

        UserDao mapper2 = sqlSession2.getMapper(UserDao.class);
        List<User> user2 = mapper2.getUser(1);
        System.out.println(user2);
        sqlSession2.close();

        UserDao mapper3 = sqlSession3.getMapper(UserDao.class);
        List<User> user3 = mapper3.getUser(1);
        System.out.println(user3);
        //关闭
        sqlSession3.close();

        inputStream.close();
    }
}

可以看到有三个蟹老板  但是sql只执行了一次

三、注解


3.1 MyBatis注解操作(注意 当使用注解的时候 开启二级缓存配置到mapper里是无效的)

通过在接口中直接添加MyBatis注解,完成CRUD。

@Select("select * from user where id = #{id}")
public User findById(Integer id);
​
@Select("select * from user")
public List<User> findAll();
​
@Insert("insert into user(name) values( #{name} )")
public void add(User user);
​
@Update("update user set name = #{name} where id = #{id}")
public void update(User user);
​
@Delete("delete from user where id = #{id}")
public void delete(Integer id);
​
//获取总记录数
@Select("select count(id) from user")
public Integer getTotalCount();


​
//获取分页数据
@Select("select * from user limit #{first},#{second}")
public List<User> findPageData(@Param("first") Integer first,@Param("second") Integer second);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

宇智波波奶茶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值