MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力。提供了OGNL表达式动态生成SQL的功能。动态SQL有:
测试1:

结果:

测试:
结果:

测试:
结果:
测试:
结果:

测试:
结果:

二级缓存是可以跨session的。




- 1、if
- 2、choose, when, otherwise
- 3、where, set
- 4、foreach
if
需求1:查询男性用户,如果输入了姓名,进行模糊查找。
/**
* 测试动态sql
* 查询男性用户,如果输入了姓名,进行模糊查找。
* @param name
* @return
*/
public List<User> queryUserLikeName(@Param("name") String name);
<select id="queryUserLikeName" resultType="User">
SELECT * FROM tb_user WHERE sex = 1
<if test="name !=null and name != ''">
AND name LIKE '%${name}%'
</if>
</select>
测试1:
@Test
public void testQueryUserLikeName(){
List<User> users = this.userMapper.queryUserLikeName("张");
for (User user : users) {
System.out.println(user);
}
}
结果:测试2:
@Test
public void testQueryUserLikeName(){
List<User> users = this.userMapper.queryUserLikeName(null);
for (User user : users) {
System.out.println(user);
}
}
choose, when, otherwise
需求2:查询男性用户,如果输入了姓名则按照姓名模糊查找,否则如果输入了年龄则按照年龄查找。
/**
* 查询男性用户,如果输入了姓名则按照姓名模糊查找,否则如果输入了年龄则按照年龄查找。
*
* @param name
* @param age
* @return
*/
public List<User> queryUserLikeNameAndAge(@Param("name") String name, @Param("age") Integer age);
<select id="queryUserLikeNameAndAge" resultType="User">
SELECT * FROM tb_user WHERE sex = 1
<choose>
<when test="age !=null and age != ''">
AND age < #{age}
</when>
<when test="name !=null and name != ''">
AND name LIKE '%${name}%'
</when>
</choose>
</select>
测试:
@Test
public void testQueryUserLikeNameAndAge(){
List<User> users = this.userMapper.queryUserLikeNameAndAge("张",null);
for (User user : users) {
System.out.println(user);
}
}
结果:
where, set
作用:完成WHERE和SET关键字,并且处理SQL语句的中语法错误。
where测试:
需求3:查询所有用户,如果输入了姓名,进行模糊查找,如果输入了年龄则按照年龄查找。
/**
* 查询所有用户,如果输入了姓名,进行模糊查找,如果输入了年龄则按照年龄查找。
*
* @param name
* @return
*/
public List<User> queryUserLikeName2(@Param("name") String name, @Param("age") Integer age);
<select id="queryUserLikeName2" resultType="User">
SELECT * FROM tb_user
<where>
<if test="name !=null and name != ''">
AND name LIKE '%${name}%'
</if>
<if test="age !=null and age != ''">
AND age < #{age}
</if>
</where>
</select>
测试:
@Test
public void testQueryUserLikeName2(){
List<User> users = this.userMapper.queryUserLikeName2(null,30);
for (User user : users) {
System.out.println(user);
}
}
结果:
SET测试:
更新数据
/**
* 更新user数据
*
* @param user
*/
public void updateUser2(User user);
<update id="updateUser2" parameterType="cn.zto.mybatis.pojo.User">
UPDATE tb_user
<set>
<if test="userName != null and userName != ''">
user_name = #{userName},
</if>
<if test="age != null and age != ''">
age = #{age},
</if>
<if test="password != null and password != ''">
password = #{password},
</if>
</set>
WHERE
id = #{id}
</update>
测试:
@Test
public void testUpdateUser2() {
User user = this.userMapper.queryUserById(2L);
user.setAge(35);
user.setPassword(null);
this.userMapper.updateUser2(user);
}
结果:
foreach
需求4:按照多个ID查询用户信息。
/**
* 按照多个ID查询用户信息。
*
* @param name
* @return
*/
public List<User> queryUserByIds(@Param("ids") List<Long> ids);
<select id="queryUserByIds" resultType="User">
SELECT * FROM tb_user WHERE id IN
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>
测试:
@Test
public void testQueryUserByIds(){
List<Long> ids = new ArrayList<Long>();
ids.add(1L);
ids.add(2L);
ids.add(3L);
List<User> users = this.userMapper.queryUserByIds(ids);
for (User user : users) {
System.out.println(user);
}
}
结果:
缓存:一级缓存
Mybatis的一级缓存的作用域是session,当openSession()后,如果执行相同的SQL(相同语句和参数),Mybatis不进行执行SQL,而是从缓存中命中返回。
原理:
Mybatis执行查询时首先去缓存区命中,如果命中直接返回,没有命中则执行SQL,从数据库中查询。

原理:
Mybatis执行查询时首先去缓存区命中,如果命中直接返回,没有命中则执行SQL,从数据库中查询。
在Mybatis中一级缓存是默认开启,并且无法关闭。
测试一级缓存:
一级缓存满足条件:
1、 同一个session中
2、 相同的SQL和参数
使用session.clearCache()强制查询不缓存。
在执行insert、update、delete时会刷新缓存。
缓存:二级缓存
Mybatis的二级缓存的作用域是一个mapper的namespace,同一个namespace中查询sql可以从缓存中命中。二级缓存是可以跨session的。
开启二级缓存:
在mapper.xml文件中加入 <cache /> 。
在mapper.xml文件中加入 <cache /> 。
注意:在Mybatis-Config中有缓存的全局控制器(cacheEnabled),默认是开启的,所以无需手动开启。
也可以手动关闭二级缓存:
二级缓存关闭后,上面测试第二次查询将从数据库查询
在<cache />标签中还有其他一些参数,如下:
可以参考mybatis官方文档