Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL 是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。
文章目录
一、动态 SQL 之if
标签
我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。比如在 id 如果不为空时可以根据 id 查询,如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。
<select id="findByCondition" resultType="User" parameterType="User">
select * from user where 1=1
<if test="username !=null and username !=''">
and username like #{username}
</if>
<if test="address !=null">
and address like #{address};
</if>
</select>
注意: 标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法。
另外要注意 where 1=1 的作用!
@Test
public void testFindByCondition() {
//5.使用代理对象执行方法
User u = new User();
u.setUsername("%王%");
u.setAddress("%北京%");
List<User> users = userDao.findByCondition(u);
for (User user :users) {
System.out.println(user);
}
}
二、动态 SQL 之where
标签
为了简化上面 where 1=1
的条件拼装,我们可以采用where
标签来简化开发
<select id="findByCondition" resultType="User" parameterType="User">
select * from user
<where>
<if test="username !=null and username !=''">
and username like #{username}
</if>
<if test="address !=null">
and address like #{address};
</if>
</where>
</select>
三、动态标签之foreach
标签
传入多个 id 查询用户信息,用下边两个 sql 实现:
SELECT * FROM USERS WHERE username LIKE '%张%' AND (id =10 OR id =89 OR id=16)
SELECT * FROM USERS WHERE username LIKE '%张%' AND id IN (10,89,16)
这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来
<select id="findUserInIds" resultType="User" parameterType="QueryVo">
<include refid="defaultUser"></include>
<where>
<if test="ids !=null and ids.size()>0">
<foreach collection="ids" open="id in (" close=")" item="id" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
<foreach>标签用于遍历集合,它的属性:
collection:代表要遍历的集合元素,注意编写时不要写#{}
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,生成的变量名,需要和#{item}名称对应
sperator:代表分隔符
@Test
public void testFindByQueryVo() {
//5.使用代理对象执行方法
QueryVo queryVo = new QueryVo();
ArrayList<Integer> list = new ArrayList<>();
list.add(41);
list.add(42);
list.add(43);
queryVo.setIds(list);
List<User> users = userDao.findUserInIds(queryVo);
for (User u : users) {
System.out.println(u);
}
}
1. 实现批量删除
/**
* 通过数组实现批量删除
*/
int deleteMoreByArray(@Param("sids") Integer[] sids);
<delete id="deleteMoreByArray">
delete from stu where sid in
<foreach collection="sids" item="sid" separator="," open="(" close=")">
#{sid}
</foreach>
</delete>
另外一种写法:
<!--int deleteMoreByArray(@Param("sids") Integer[] sids);-->
<delete id="deleteMoreByArray">
delete from stu where
<foreach collection="sids" item="sid" separator="or">
sid = #{sid}
</foreach>
</delete>
@Test
public void testDeleteMoreByArray(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
int result = mapper.deleteMoreByArray(new Integer[]{11, 12, 13});
System.out.println(result);
}
第二种方式的SQL语句执行结果:
2. 实现批量增加
/**
* 通过list集合实现批量添加
*/
int insertMoreByList(@Param("stus") List<Student> stus);
<!--int insertMoreByList(@Param("stus") List<Student> stus);-->
<insert id="insertMoreByList">
insert into stu values
<foreach collection="stus" item="stu" separator=",">
(#{stu.sid},#{stu.sname},#{stu.score},null)
</foreach>
</insert>
@Test
public void testInsertMoreByList(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
Student stu1 = new Student().setSid(11).setSname("11").setScore(11);
Student stu2 = new Student().setSid(12).setSname("12").setScore(12);
Student stu3 = new Student().setSid(13).setSname("13").setScore(13);
List<Student> stus = Arrays.asList(stu1, stu2, stu3);
System.out.println(mapper.insertMoreByList(stus));
}
四、Mybatis 中简化编写的 SQL 片段
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。
<!-- 抽取重复的语句代码片段 -->
<sql id="defaultSql">
select * from user
</sql>
比如查询语句:select sid,sname,score from stu
可以简化为:将 sid,sname,score 抽取出来
<sql id="stuColumns">sid,sname,score</sql>
select <include refid="stuColumns"></include> from stu
五、trim 标签
若标签中有内容时:
prefix|suffix
:将 trim 标签中内容前面或后面添加指定内容
suffixOverrides|prefixOverrides
:将trim标签中内容前面或后面去掉指定内容
若标签中没有内容时,trim 标签也没有任何效果
如果不加 trim,则一旦出现某个字段为空, and 和 or 就会拼接错误
/**
* 多条件查询
*/
List<Student > getStuByCondition(Student student);
<!--List<Student> getStuByCondition(Student student);-->
<select id="getStuByCondition" resultType="Student">
select * from stu
<trim prefix="where" suffixOverrides="and|or">
<if test="sid != null and sid != ''">
sid = #{sid} and
</if>
<if test="sname != null and sname != ''">
sname = #{sname} or
</if>
<if test="score != null and sex != ''">
score = #{score} and
</if>
</trim>
</select>
@Test
public void testGetStuByCondition(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
List<Student> list = mapper.getStuByCondition(new Student(4, "Max", null));
System.out.println(list);
}
六、choose、when、otherwise 标签
choose、when、otherwise
,相当于if...else if...else
when
至少要有一个,otherwise
最多只能有一个
/**
* 测试choose、when、otherwise
*/
List<Student> getStuByChoose(Student student);
<!--List<Student> getStuByChoose(Student student);-->
<select id="getStuByChoose" resultType="Student">
select * from stu
<where>
<choose>
<when test="sid != null and sid != ''">
sid = #{sid}
</when>
<when test="sname != null and sname != ''">
sname = #{sname}
</when>
<when test="score != null and score != ''">
score = #{score}
</when>
<otherwise>
sid = 5
</otherwise>
</choose>
</where>
</select>
@Test
public void testGetStuByChoose(){
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
DynamicSQLMapper mapper = sqlSession.getMapper(DynamicSQLMapper.class);
List<Student> list = mapper.getStuByChoose(new Student(null, "", null));
System.out.println(list);
}