mybatis中映射文件的SQL深入:动态SQL标签、标签、标签
1.1 概述
- mybatis的映射文件中,前面我们的SQL都是比较简单的,有些业务逻辑复杂的时候,我们的SQL是动态变化的。
1.2 动态SQL之<if>标签
- 我们根据实体类的不同取值,使用不同的SQL语句来进行查询。比如在id如果不为空时可以根据id查询,如果username不同空时还要加入用户名作为条件。这种情况我们在多条件组合查询中经常会使用到。
1.需求:根据id或者名称查询。
2.dao 查询方法
public interface IUserDao {
/**
* 查询全部
*/
List<User> findAll();
/**
* 条件查询,根据id或username查询
*/
List<User> findByCondition(User user);
}
3.接口映射: IUserDao.xml
<!-- 动态SQL
<if> 条件判断标签
test 属性,用来判断的表达式,返回boolean类型
test="id != 0" 这里的id就是parameterType中User对象的id属性。
这里的id也是获取对象的id属性值。
-->
<select id="findByCondition" parameterType="user" resultType="user">
select * from user where 1=1
<!-- 判断 -->
<if test="id != 0">
and id=#{id}
</if>
<if test="username != null">
and username=#{username}
</if>
</select>
4.测试
public class UserDaoTest {
private InputStream in;
private SqlSession session;
private IUserDao userDao;
// 每次再执行junit测试方法之前执行
@Before
public void before() throws IOException {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
session = factory.openSession();
userDao = session.getMapper(IUserDao.class);
}
@After
public void close() throws IOException {
//关闭
session.commit();
session.close();
in.close();
}
@Test
public void find() throws IOException {
User user = new User();
user.setId(46);
user.setUsername("马云");
//执行方法
List<User> list = userDao.findByCondition(user);
System.out.println(list);
}
}
1.3 动态SQL之<where>标签
通过<where>标签拼接where条件,简化where写法。
<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>
</where>
</select>
1.4 动态标签之<foreach>标签
- 作用:遍历参数值
- 查询需求:根据多个id查询
SELECT * FROM USER WHERE id=41 OR id=42
SELECT * FROM USER WHERE id IN (41,42)- 定义查询扩展对象,封装多个id值
/** 当前QueryVo支持User对象的所有属性查询以及扩展属性
*/
public class QueryVo extends User {
// 条件:多个id
private List<Integer> ids;
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
}
dao接口、映射
!--多个id查询-->
<!--SELECT * FROM USER WHERE 1=1 and id IN (41,42)-->
<!--
foreach
collection 遍历的集合
open 再sql语句中最先拼接的部分。遍历的开始
close 再sql语句后最后拼接的部分。遍历的结束
separator 每一次遍历中,拼接sql语句时候以指定的分割符分割(逗号)
item 存储每一次遍历的结果
index 当前遍历元素的索引
-->
<select id="findByCondition2" parameterType="queryvo" resultType="user">
SELECT * FROM USER WHERE 1=1
<if test="ids != null and ids.size()>0">
<foreach collection="ids" open="and id IN (" separator="," close=")" item="id">
#{id}
</foreach>
</if>
</select>
测试:
@Test
public void find2() throws IOException {
// 条件
QueryVo queryVo = new QueryVo();
List<Integer> ids = new ArrayList<>();
ids.add(46);
ids.add(48);
ids.add(41);
// 设置条件
queryVo.setIds(ids);
//执行方法
List<User> list = userDao.findByCondition2(queryVo);
System.out.println(list);
}
1.5 mybatis中简化的SQL片段
- Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。我们先到 UserDao.xml 文件中使用<sql>标签,定义出公共部分。
- <!--
sql标签:定义SQL片段,抽取公用的SQL部分
include标签: 用来引用sql片段
-->
<sql id="selectUser">
SELECT * FROM USER WHERE 1=1
</sql>
<select id="findByCondition2" parameterType="queryvo" resultType="user">
<!--引用SQL片段-->
<include refid="selectUser"></include>
<if test="ids != null and ids.size()>0">
<foreach collection="ids" open="and id IN (" separator="," close=")" item="id">
#{id}
</foreach>
</if>
</select>再通过<include>标签的 refid 属性的值就是<sql> 标签定义 id 的取值。
注意:如果引用其它 mapper.xml 的 sql 片段,则在引用时需要加上 namespace,如下:
<include refid="namespace.sql 片段”/>