一、MyBatis接口绑定方案与多参数传递
1.作用
实现创建与mapper.xml相对应的接口后,mybatis通过读取mapper.xml内的信息生成对应的接口实现类,通过调用接口对象就可以获取mapper.xml中编写的sql,体现了DIP(Dependence Inversion Principle) 依赖反转原则的设计原则,在SSM的整合中使用的也是这种方案。
2.实现步骤
2.1创建一个接口类
接口类的包名和接口名需要和mapper.xml中的namespace值相同,接口方法名和mapper.xml中标签的id值相同。此处使用了param注解会构建一个map传入sql中,其中map的key为param中的属性,value为传入的值。
package com.xxbb.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
public interface UserMapper {
List<?> queryUser(@Param("pageStart") String pageStart,@Param("pageSize") String pageSize);
}
传入参数为多个时可以省略parameterType属性。在对应的xml中使用map的key获取值。如果未设置param注解,则在map中按传入值顺序获取值。如果传入的值是实体类,可以通过map的key.属性名获取。
<?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">
<!-- namespace理解为实现类的全路径 包加类名 -->
<mapper namespace="com.xxbb.mapper.UserMapper">
<!-- id=方法名
如果方法的返回值是List,在resultType写List的泛型,
因为mybatis是对JDBC封装,一行一行读取数据
-->
<select id="queryUser" resultType="User">
select * from t_user limit #{pageInfo1.pageNumber},#{pageInfo2.pageSize}
<!-- select * from t_user limit #{0},#{1} -->
<!-- select * from t_user limit #{param1},#{param2} -->
<!-- select * from t_user limit #{pageStart},#{pageSize} -->
</select>
</mapper>
2.2在mybatis的配置文件中配置接口接口所在包名和mapper路径。(注意在mappers中mapper和package的先后顺序)
<mappers>
<package name="com.xxbb.mapper"/>
</mappers>
2.3接口的使用
编写好sql语句,创建好接口方法后,进行如下操作:
InputStream is=Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
UserMapper userMapper=session.getMapper(UserMapper.class);
List<?> res=userMapper.queryUser(0, 2);
查询结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Zrivf7NQ-1584809919180)(D:\TyporaPhoto\image-20200321225813033.png)]
此过程中使用getMapper方法创建了一个UserMapper接口的实现类,调用queryUser方法
二、动态SQL
可根据不同的条件需要执行不同的SQL命令,在mapper.xml中添加逻辑判断等。
1.if标签
和java中if的使用方式相似
<select id="queryUser" resultType="User">
select * from t_user
<if test="pageStart!=null and pageSize!=null and pageStart!='' and pageSize!=''">
limit #{pageStart},#{pageSize}
</if>
</slect>
2.choose ,when,otherwise标签
choose类似于switch,when表示switch中的case,otherwise表示defaut
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
3.where,trim,set标签
3.1where:
如果where标签中有内容,且第一个是and或者or则会替换成where
<select id="queryUser" resultType="User">
select * from t_user
<where>
<if test="pageStart!=null and pageStart!=''">
and id =#{pageStart}
</if>
</where>
</select>
3.2set:
动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的SQL 语句的后面留下这些逗号。
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
如果此时bio!=null的值为false,则上一句最后的逗号就多余了,set会自动删除
3.2trim:
在指定位置修改内容。执行顺序先删除后添加
-
prefix:在语句前添加内容,即添加前缀值
-
prefixOverrides:删除语句前指定字段的内容
<trim prefix="WHERE" prefixOverrides="AND |OR "> AND id=#{id} </trim>
prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容。
-
suffix:在语句后添加内容,即添加后缀值
-
suffixOverrides:删除语句后端指定字段的内容
<trim suffix="AND" suffixOverrides=","> AND id=#{id}, </trim>
4.foreach标签
循环参数内容,在语句前端添加内容,在语句后端添加内容,可用于in语句和批量新增的场景中,
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。
注意 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
5.bind标签
可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。常用于模糊查询
<select id="selectBlogsLike" resultType="Blog">
2. <bind name="pattern" value="'%' + pattern + '%'" />
3. SELECT * FROM BLOG
4. WHERE title LIKE #{pattern}
5. </select>
6.sql和include标签
这个元素可以被用来定义可重用的 SQL 代码段,这些 SQL 代码可以被包含在其他语句中。它可以(在加载的时候)被静态地设置参数。 在不同的包含语句中可以设置不同的值到参数占位符上。
<select id="selectUsers" resultType="map">
select
<include refid="userColumns"><property name="alias" value="t1"/></include>,
<include refid="userColumns"><property name="alias" value="t2"/></include>
from some_table t1
cross join some_table t2
</select>
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
属性值也可以被用在 include 元素的 refid 属性里或 include 元素的内部语句中。
<sql id="sometable">
${prefix}Table
</sql>
<sql id="someinclude">
from
<include refid="${include_target}"/>
</sql>
<select id="select" resultType="map">
select
field1, field2, field3
<include refid="someinclude">
<property name="prefix" value="Some"/>
<property name="include_target" value="sometable"/>
</include>
</select>