一、动态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);

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


(隔壁王大爷都学会了!)&spm=1001.2101.3001.5002&articleId=120670174&d=1&t=3&u=3fb4c980fa8240c1967a21e3b237e373)
765

被折叠的 条评论
为什么被折叠?



