MyBatis有一个强大特性就是它的动态SQL。在实际项目开发中,经常需要根据不同条件拼接SQL语句,拼接时还要确保不能忘了必要的空格,有时候还要注意省掉列名列表最后的逗号...等等。在使用JDBC 或其他类似持久层框架操作数据库时,处理这种情况是非常麻烦的,甚至可以用痛苦来形容,而在MyBatis中利用动态SQL这一特性可以很简单地解决这个问题。
动态SQL元素和使用JSTL或其他类似基于XML的文本处理器相似,MyBatis采用功能强大的基于OGNL的表达式来完成动态SQL。OGNL 的表达式可以被用在任意的SQL 映射语句中。
如上,假设有如上一张表,我们想查询如下条件:
- status=1
- 公司名包含【华为】
- 品牌名包含【华为】
则在映射文件中书写如下sql语句:
<select id="selectByCondition" resultMap="brandResultMap">
select * from tb_brand where status=#{status} and company_name like #{companyName}
and brand_name like #{brandName}
</select>
接口中的方法名:
List<Brand> selectByCondition(@Param("status") int status,
@Param("companyName")String companyName,
@Param("brandName")String brandName);
测试类如下:
public void testselectByCondition() throws IOException {
int status=1;
String companyName="华为";
String brandName="华为";
companyName="%"+companyName+"%";
brandName="%"+brandName+"%";
// 1.获取SqlSessionFactory
String resource ="mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
// 2.获取SqlSession对象
SqlSession sqlSession= sqlSessionFactory.openSession();
// 3.获取Mapper接口的代理对象
BrandMapper brandMapper=sqlSession.getMapper(BrandMapper.class);
// 4.执行方法
List<Brand> brands=brandMapper.selectByCondition(status,companyName,brandName);
System.out.println(brands);
// 5.释放资源
sqlSession.close();
}
查询结果:
但是在实际场景中,可能并不需要同时查询3个条件,这样的话,参数值无法传入给sql中的占位符,后台会发生语法错误~
此时用到Mybatis中的动态sql技术:
修改sql语句如下:
<select id="selectByCondition" resultMap="brandResultMap">
select * from tb_brand where
<if test="status!=null">
status=#{status}
</if>
<if test="company_name!=null and company_name!=''">
and company_name like #{companyName}
</if>
<if test="brand_name!=null and brand_name!=''">
and brand_name like #{brandName}
</if>
</select>
如上,当有条件不存在时,会直接省略对该条件的判断。
<select id="selectByCondition" resultMap="brandResultMap">
select * from tb_brand
<where>
<if test="status!=null">
status=#{status}
</if>
<if test="companyName!=null and companyName!=''">
and company_name like #{companyName}
</if>
<if test="brandName!=null and brandName!=''">
and brand_name like #{brandName}
</if>
</where>
</select>
但是还存在bug,当第一个条件不存在时会直接导致关键字where和and相连接导致语法错误,将where标签嵌到外面即可解决~