MyBatis映射文件深入
动态sql语句
1. 动态sql语句概述
Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,
此时在前面的学习中我们的 SQL 就不能满足要求了。
参考的官方文档,描述如下:
这里主要讲解 if 和 foreach
2. 动态 SQL 之< if >
我们根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果
username 不为空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。(有时候前端发送来的数据是不确定的,这个时候在dao层查询时会比较复杂,学 Mybatis 之前是用字符串拼接
的方式查询,学了 Mybatis 之后,用下面的方式解决)
接口
public interface UserMapper {
User findByCondition(User condition);
}
映射文件
<mapper namespace="com.xiafanjun.dao.UserMapper"></mapper>
<!--根据不同的条件查询-->
<select id="findByCondition" parameterType="user" resultType="user">
select * from user
<where>
<if test="id!=0">
and id = #{id}
</if>
<if test="username!=null">
and username = #{username}
</if>
<if test="password!=null">
and password = #{password}
</if>
</where>
</select>
</mapper>
当查询条件id和username都存在时,控制台打印的sql语句如下:
public class TestProxyDao {
public static void main(String[] args) throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
SqlSession sqlSession = build.openSession();
//模拟前端传来的数据
User condition = new User();
condition.setId(1);
condition.setUsername("tom");
// 获得 MyBatis 框架生成的 UserMapper 接口的实
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findByCondition(condition);
//打印结果
System.out.println(user);
sqlSession.close();
}
}
当查询条件只有id存在时,控制台打印的sql语句如下:
public class TestProxyDao {
public static void main(String[] args) throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
SqlSession sqlSession = build.openSession();
//模拟前端传来的数据
User condition = new User();
condition.setId(1);
//condition.setUsername("tom");
// 获得 MyBatis 框架生成的 UserMapper 接口的实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findByCondition(condition);
//打印结果
System.out.println(user);
sqlSession.close();
}
}
3. 动态 SQL 之< foreach >
循环执行sql的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,3)
(SELECT * FROM USER WHERE id=1 or id=3)
映射文件
<mapper namespace="com.xiafanjun.dao.UserMapper">
<!--foreach 循环执行sql拼接操作-->
<select id="findByIds" resultType="user" parameterType="list">
select * from user
<where>
<foreach collection="list" open="id in (" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>
</mapper>
foreach标签的属性含义如下:
< foreach >标签用于遍历集合,它的属性:
-
collection:代表要遍历的集合元素,注意编写时不要写#{}
-
open:代表语句的开始部分
-
close:代表结束部分
-
item:代表遍历集合的每个元素,生成的变量名
-
sperator:代表分隔符
测试代码片段
public class TestProxyDao {
public static void main(String[] args) throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory build = sqlSessionFactoryBuilder.build(resourceAsStream);
SqlSession sqlSession = build.openSession();
//模拟前端传来的id集合
List<Integer> ids = new ArrayList();
ids.add(1);
ids.add(3);
// 获得 MyBatis 框架生成的 UserMapper 接口的实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.findByIds(ids);
System.out.println(userList);
sqlSession.close();
}
}
SQL片段抽取
在映射文件中,我们可以发现,findByCondition 和 findByIds 都有 sql 语句 select * from user ,当需求改变 sql 语句需要修改时,我们要修改的 sql 语句会很多,所以我们要将 select * from user 抽取出来。
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的
<mapper namespace="com.xiafanjun.dao.UserMapper">
<!-- sql抽取 -->
<sql id="selectUser">select * from user</sql>
<!--根据不同的条件查询-->
<select id="findByCondition" parameterType="user" resultType="user">
<include refid="selectUser"/>
<where>
<if test="id!=0">
and id = #{id}
</if>
<if test="username!=null">
and username = #{username}
</if>
<if test="password!=null">
and password = #{password}
</if>
</where>
</select>
<!--foreach 循环执行sql拼接操作-->
<select id="findByIds" resultType="user" parameterType="list">
<include refid="selectUser"/>
<where>
<foreach collection="list" open="id in (" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>
</mapper>
知识小结
MyBatis映射文件配置:
< select >:查询
< insert >:插入
< update >:修改
< delete >:删除
< where >:where条件
< if >:if判断
< foreach >:循环
< sql >:sql片段抽取