通过mybatis提供的各种标签方法实现动态拼接sql。
需求:根据性别和名字查询用户
查询sql:
SELECT id, username, birthday, sex, address FROM user
WHERE sex = 1 AND username LIKE '%张%'
UserMapper.xml配置sql,如下:
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM user
WHERE sex = #{sex} AND username LIKE
'%${username}%'
</select>
编写Mapper接口,如下图:
在UserMapperTest添加测试方法,如下:
Test
public void testQueryUserByWhere() {
// mybatis和spring整合,整合之后,交给spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 创建Mapper接口的动态代理对象,整合之后,交给spring管理
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 使用userMapper执行根据条件查询用户
User user = new User();
user.setSex("1");
user.setUsername("张");
List<User> list = userMapper.queryUserByWhere(user);
for (User u : list) {
System.out.println(u);
}
// mybatis和spring整合,整合之后,交给spring管理
sqlSession.close();
}
测试效果如下图:
如果注释掉 user.setSex("1"),测试结果如下图:
测试结果二很显然不合理。
按照之前所学的,要解决这个问题,需要编写多个sql,查询条件越多,需要编写的sql就更多了,显然这样是不靠谱的。
解决方案,使用动态sql的if标签。
我们使用if标签来解决问题:
改造UserMapper.xml,如下:
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM user
WHERE 1=1
<if test="sex != null and sex != ''">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
</if>
</select>
注意字符串类型的数据需要要做不等于空字符串校验。
效果如下:
继续改造上面的例子
上面的sql还有where 1=1 这样的语句,很麻烦,可以使用where标签进行改造
改造UserMapper.xml,如下:
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM user
<where>
<if test="sex != null">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
</if>
</where>
</select>
测试效果如下:
Sql片段
Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。
把上面例子中的id, username, birthday, sex, address提取出来,作为sql片段,如下:
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT <include refid="userFields" /> FROM user
<where>
<if test="sex != null">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
</if>
</where>
</select>
<sql id="userFields">
id, username, birthday, sex, address
</sql>
如果要使用别的Mapper.xml配置的sql片段,可以在refid前面加上对应的Mapper.xml的namespace
例如下图:
foreach的使用方法:
向sql传递数组或List,mybatis使用foreach解析,如下:
根据多个id查询用户信息
我们传入的是POJO的包装类
查询sql:
SELECT * FROM user WHERE id IN (1,10,24)
如下图在pojo中定义list属性ids存储多个用户id,并添加getter/setter方法:
编写Mapper.xml
UserMapper.xml添加sql,如下:
<select id="queryUserByIds" parameterType="queryVo" resultType="User">
SELECT * FROM
user
<where>
<foreach collection="ids" item="item" open="id IN (" close=")"
separator=",">
#{item}
</foreach>
</where>
</select>
测试方法如下图:
@Test
public void testQueryUserByIds() {
// mybatis和spring整合,整合之后,交给spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 创建Mapper接口的动态代理对象,整合之后,交给spring管理
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 使用userMapper执行根据条件查询用户
QueryVo queryVo = new QueryVo();
List<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(10);
ids.add(24);
queryVo.setIds(ids);
List<User> list = userMapper.queryUserByIds(queryVo);
for (User u : list) {
System.out.println(u);
}
// mybatis和spring整合,整合之后,交给spring管理
sqlSession.close();
}
测试效果如下图:
我们传入的是是List的时候
配置文件应该修改成相应的
我们传入的是数组的时候