在mybatis中,它提供了一些动态sql标签,可以使mybatis的开发更快捷,这些动态sql可以使sql有更高的可重用性。。
常用的动态sql标签:
- if
- where
- set
- choose(when,otherwise)
- trim
- foreach
项目目录结构
1.if标签
if标签:可以对输入的参数进行判断,test属性为判断表达式
UserMapper接口
package com.test.mapper;
import java.util.List;
import java.util.Map;
import com.test.domain.User;
import com.test.domain.UserQueryVo;
public interface UserMapper {
User findUserByName(UserQueryVo uv);
}
UserMapper.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.test.mapper.UserMapper">
<select id="findUserByName" parameterType="com.test.domain.UserQueryVo" resultType="com.test.domain.User">
SELECT * FROM USER WHERE
<if test="user != null">
<if test="user.username != null and user.username != ''">
username like '%${user.username}%'
</if>
<if test="user.sex != null and user.sex != ''">
AND sex = #{user.sex}
</if>
</if>
</select>
</mapper>
全局配置文件 SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<!-- 配置JDBC事务控制,由mybatis进行管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源,采用mybatis连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<mapper resource="mapper/UserMapper.xml" />
</mappers>
</configuration>
测试代码
@Test
public void test_04(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserQueryVo uv = new UserQueryVo();
User user = new User();
user.setUsername("五");
user.setSex("2");
uv.setUser(user);
User user2 = userMapper.findUserByName(uv);
System.out.println(user2);
}
测试结果
DEBUG [main] - ==> Preparing: SELECT * FROM USER WHERE username like '%五%' AND sex = ?
DEBUG [main] - ==> Parameters: 2(String)
DEBUG [main] - <== Total: 1
User [id=1, username=王五, sex=2, birthday=null, address=null]
通过以上代码可以发现,当username为null,sex不为空时,sql语句就变为SELECT * FROM USER WHERE AND sex = ? WHERE AND 产生多余的sql关键字导致报错,这时就引入where标签
2.if和where标签配合使用
where 元素知道只有在一个以上的if条件匹配的情况下才去插入”WHERE”子句。而且,若最后的内容是”AND”或”OR”开头的,where 元素也知道如何将他们去除。
修改UserMapper.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.test.mapper.UserMapper">
<select id="findUserByName" parameterType="com.test.domain.UserQueryVo" resultType="com.test.domain.User">
SELECT * FROM USER
<where>
<if test="user != null">
<if test="user.username != null and user.username != ''">
AND username like '%${user.username}%'
</if>
<if test="user.sex != null and user.sex != ''">
AND sex = #{user.sex}
</if>
</if>
</where>
</select>
</mapper>
注:where标签默认去掉where后面的第一个AND 或者OR,如果没有匹配的条件就会把自己where删除(自杀)
3.if和set标签配合使用
set标签和表where标签一样回自动的添加set关键字,如果没有条件匹配会把自己也删除,同时也会消除无关的逗号,因为用了条件语句之后很可能就会在生成的赋值语句的后面留下这些逗号。
UserMapper接口
package com.test.mapper;
import java.util.List;
import java.util.Map;
import com.test.domain.User;
import com.test.domain.UserQueryVo;
public interface UserMapper {
void updataUserById(User user);
}
UserMapper.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.test.mapper.UserMapper">
<update id="updataUserById">
update user
<set>
<if test="username != null">
username = #{username},
</if>
<if test="sex != null">
sex = #{sex}
</if>
</set>
where id = #{id}
</update>
</mapper>
测试代码
@org.junit.Test
public void test_07(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("凯");
user.setSex("2");
user.setId(1);
userMapper.updataUserById(user);
sqlSession.commit();
sqlSession.close();
}
4.foreach标签
foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach元素的属性主要有item,index,collection,open,separator,close。item表示集合中每一个元素进行迭代时的别名,index指定一个名字,用于表示在迭代过程中,每次迭代到的位置,open表示该语句以什么开始,separator表示在每次进行迭代之间以什么符号作为分隔符,close表示以什么结束,在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有三种情况:
1.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list .
2.如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array .
3.如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key.
4.如果使用的是包装类封装的List与Map一样,将类属性当作Map的key就行
4.1传递List参数
UserMapper接口
package com.test.mapper;
import java.util.List;
import java.util.Map;
import com.test.domain.User;
import com.test.domain.UserQueryVo;
public interface UserMapper {
List<User> findUserByIds(List<Integer> list);
}
UserMapper.xml
<select id="findUserByIds" parameterType="list" resultType="com.test.domain.User" >
select * from user
<where>
<if test="list != null">
AND id IN
<foreach collection="list" open="(" item="id" close=")" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
测试代码
@Test
public void test_08(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<Integer> idList = new ArrayList<Integer>();
idList.add(1);
idList.add(10);
idList.add(16);
idList.add(22);
List<User> userList = userMapper.findUserByIds(idList);
sqlSession.close();
System.out.println(userList);
}
4.1传递包装类封装List参数
UserMapper接口
package com.test.mapper;
import java.util.List;
import java.util.Map;
import com.test.domain.User;
import com.test.domain.UserQueryVo;
public interface UserMapper {
List<User> findUserByIds(UserQueryVo uv);
}
UserMapper.xml
<select id="findUserByIds" parameterType="com.test.domain.UserQueryVo" resultType="com.test.domain.User" >
select * from user
<where>
<if test="idList != null">
AND id IN
<foreach collection="idList" open="(" item="id" close=")" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
测试代码
@Test
public void test_08(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<Integer> idList = new ArrayList<Integer>();
idList.add(1);
idList.add(10);
idList.add(16);
idList.add(22);
UserQueryVo uv = new UserQueryVo();
uv.setIdList(idList);
List<User> userList = userMapper.findUserByIds(uv);
sqlSession.commit();
sqlSession.close();
System.out.println(userList);
}