一、动态SQL语句
- 普通SQL语句查询
假设我们需要对Product表进行查询,不仅要查询所有,更要求模糊查询。
通常情况下,我们会写两条SQL语句,执行两次方法来得到我们想要的效果。
TestProduct.java
System.out.println("查询所有的");
List<Product> ps = session.selectList("listProduct");
for(Product p : ps){
//这里直接输出的就是一个对象的地址
System.out.println(p);
}
System.out.println("模糊查询");
Map<String, Object> params = new HashMap<>();
params.put("name", "果");
List<Product> ps2 = session.selectList("listProductByName", params);
for(Product p : ps2){
System.out.println(p);
}
Product.xml
其实我们可以发现,这里即使我们传入了参数name,在select标签的属性中也没有parameterType这么一个属性。因此这个背后存在MyBatis的自动赋值的操作。
<select id = "listProduct" resultType = "Product">
select * from product
</select>
<select id = "listProductByName" resultType = "Product">
select * from product where name like concat('%', #{name}, '%')
</select>
输出结果:
默认输出的会是一个对象的地址,而不是一个对象的形式。
如果我们想要输出的是一个对象的形式,就需要重写toString()方法。——在Product.java中重写。
@Override
public String toString() {
return "Product[id=" + id + ",name=" + name + ",price=" + price + "]";
}
重新运行TestProduct.java
- if标签
if标签是对前面那种情况的一种更为方便的操作。如果没有传递参数name,那么就是查询所有;如果传递了name参数,那么就是进行模糊查询。
这样只需要定义一条sql语句就可以应付多种情况了,在测试的时候,也只需要调用这么一条语句所对应的id了。
Product.xml
<select id = "listProduct" resultType = "Product">
select * from product
<if test = "name != null">
where name like concat('%', #{name}, '%')
</if>
</select>
可以看到,我们其实是将之间的两条SQL语句整合成为了一条。用一个if判断来表示最终执行的真实语句。if标签的test属性中判断的条件。
TestProduct.java
System.out.println("查询所有的");
List<Product> ps = session.selectList("listProduct");
for(Product p : ps){
System.out.println(p);
}
System.out.println("模糊查询");
Map<String, Object> params = new HashMap<>();
params.put("name", "果");
List<Product> ps2 = session.selectList("listProduct", params);
for(Product p : ps2){
System.out.println(p);
}
相比于前面的,此处的代码只进行了一处改动,就是将模糊查询中的方法名进行了改变,其他的地方都没有变动。
- where标签
多条件的矛盾:
<select id="listProduct" resultType="Product">
select * from product
<if test="name!=null">
where name like concat('%',#{name},'%')
</if>
<if test="price!=0">
and price > #{price}
</if>
</select>
如果我们在传参时,没有传入name这个参数,而是传入了price。那么我们的SQL语句就变成了“select * from product and price > #{price}”,而这个SQL语句显然是不正确的,缺少了where而多了一个and。where标签就是起这个作用的。
<select id = "listProduct" resultType = "Product">
select * from product
<where>
<if test = "name != null">
where name like concat('%', #{name}, '%')
</if>
<if test = "price != null and price != 0">
and price > #{price}
</if>
</where>
</select>
<where>标签会进行自动判断,如果任何条件都不成立,那么就在sql语句里就不会出现where关键字;如果有任何条件成立,会自动去掉多出来的 and 或者 or
- set标签
set标签的作用与where标签的效果其实具有相似之处。因为在update中我们也会遇到类似的问题,要不要加set,要不要去掉或者补充多余的and和or。
Product.xml
<update id = "updateProduct">
update product
<set>
<if test = "name != null">name = #{name},</if>
<if test = "price != null">price = #{price}</if>
</set>
where id = #{id}
</update>
一定要在在name=#{name}的后面加入一个逗号,否则运行程序的时候会报SQL的错误。
- trim标签
trim标签可以用来定制想要的功能。例如我们之间的where标签和set标签其实都可以用trim标签来统一。
利用trim标签更改完对应的SQL语句之后,仍然能出来相应的效果。
<select id = "listProduct" resultType = "Product">
select * from product
<trim prefix = "where" prefixOverrides = "and|or">
<if test = "name != null">
where name like concat('%', #{name}, '%')
</if>
<if test = "price != null and price != 0">
and price > #{price}
</if>
</trim>
</select>
<update id = "updateProduct" parameterType = "Product">
update product
<trim prefix = "set" prefixOverrides = ",">
<if test = "name != null">name = #{name},</if>
<if test = "price != null"> price = #{price}</if>
</trim>
where id = #{id}
</update>
我试过了,prefix里面的where和set大小写都可以成功。
- choose标签
Mybatis里面没有else标签,但是可以使用when otherwise标签来达到这样的效果。
其作用是: 提供了任何条件,就进行条件查询,否则就使用id>1这个条件。
数据库:
TestProduct.java
System.out.println("多条件查询");
Map<String, Object> params = new HashMap<>();
params.put("name", "果");
params.put("price", "5");
List<Product> ps3 = session.selectList("listProduct", params);
for(Product p : ps3){
System.out.println(p);
}
Product.xml
<select id = "listProduct" resultType = "Product">
select * from product
<where>
<choose>
<when test = "name != null">
and name like concat('%', #{name}, '%')
</when>
<when test = "price != null">
and price > #{price}
</when>
<otherwise>
and id > 1
</otherwise>
</choose>
</where>
</select>
查询结果:
从数据库中存储的数据以及查询的结果来看,when otherwise中的语句只会执行其中的一条,如果前面的when都不满足,就只执行otherwise;而前面的when中,只会对满足条件的第一个when执行,后面的都不再执行。不太像if-else,更像是switch-case。
- forEach标签
<select id = "listProduct" resultType = "Product">
select * from product
where id in
<foreach item = "item" index = "index" collection="list" open = "("
separator = "," close = ")">
#{item}
</foreach>
</select>
对于forEach标签中的每个属性:
- item:集合中每一个元素进行迭代时的别名
- index表示在迭代过程中,每次迭代到的位置
- open:表示语句以什么开始
- separator:每次进行迭代之间以什么符号作为分隔符
- close:表示语句以什么结束
- collection:如果传入的参数是单参数且参数类型是一个List时,collection的值是list;如果传入的是单参数且参数类型是一个array数组时,collection的值是array;如果传入的参数是多个的时候,我们就需要把它的类型封装成Map了。
List<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(3);
ids.add(5);
List<Product> ps = session.selectList("listProduct", ids);
for(Product p : ps){
System.out.println(p);
}
二、练习分页
Map<String, Object> params = new HashMap<>();
params.put("start", 0);
params.put("count", 5);
List<Category> cs = session.selectList("listCategory", params);
for(Category c : cs){
System.out.println(c);
}
<select id = "listCategory" resultType = "Category">
select * from category_
<if test = "start != null and count != null">
limit #{start}, #{count}
</if>
</select>
不知道为什么,不是按照id的顺序正常的排列下来。
三、PageHelper插件实现分页
mybatis-config.xml
<plugins>
<plugin interceptor = "com.github.pagehelper.pageInterceptor">
</plugin>
</plugins>
PageHelper.offsetPage(0, 5);
List<Category> cs = session.selectList("listCategory");
for(Category c : cs){
System.out.println(c.getName());
}
PageInfo pageInfo = new PageInfo<>(cs);
System.out.println("总数:" + pageInfo.getTotal());
System.out.println(pageInfo);
在实现分页的时候,突然间发现控制台出现了错误;连前面可以运行出来的结果都在报错;猜测是jar包出现了问题。导致PageHelper实现分页失败。