代理开发
概念
为什么本片文章要以’高级’,与’应用’来有别于上一篇文章呢?这是因为上一篇文章(https://blog.csdn.net/chinatopno1/article/details/105209751)所介绍的Mybatis只是为了让人们清楚Mybatis的思想和理论以及基础.实际开发中,Mybatis的用法还是同上一篇文章有区别的.
比如上一篇文章着重强调用SQL操作配置文件来替代Dao层的实现类,但实际上却没有完全应用到Dao层的接口,也没有完全发挥作为实现类替代品应有的作用.
而这一篇文章,会介绍如何真真正正的通过sql操作配置文件来替代Dao层,而这个’真真正正’指的就是实际开发当中使用的’Mybatis代理开发’
什么是代理开发?
看下图
标签的属性介绍
我们需要在’SQL操作配置文件’中的’mapper’围堵标签内定义select(查询),inster(增加),delete(删除),update(更改)这四个标签.
而这四个标签则都需要声明3个属性.
属性一:parameterType
方法形参类型标签
当Dao层内的方法存在形参时,那么需要把parameterType内的参数定义为对应的类型.
如果参数是基本数据类型,那么可以参考以下的表:
如果是其它数据类型,则需要指定数据类型的包路径
如果方法处没有参数列表,则直接去掉’parameterType’属性
属性二:resultType 方法返回值类型标签
同样是在resultType处声明一个同方法的返回值类型相对应的包路径.
如果参数是基本数据类型,那么可以参考以下的表:
如果是其它数据类型的返回值,则需要指定数据类型的包路径
如果方法处没有返回值类型,则直接去掉’resultType’属性
应用
如果接口方法中的参数列表较为特殊,那么参考这篇文章:https://blog.csdn.net/chinatopno1/article/details/105260386
步骤一.配置SQL操作文件
格式:
<选择一个增删改查标签 id="Dao接口的方法名" parameterType="Dao接口方法中的形参类型" resultType="Dao接口方法中的返回值">
//SQL语句
</选择一个增删改查标签>
</mapper>
步骤二:在Service层实例化Dao接口对象,并执行SQL语句
一.实例化Dao接口对象之格式:
Dao接口类名 自定义Dao接口实例化对象名 = 自定义sqlSession对象名.getMapper(Dao接口类名.class);
列如:
UserDao daoObj = sqlSessionObj.getMapper(UserDao.class);
二.执行SQL语句之格式:自定义Dao接口实例化对象名.Dao接口方法名();
列如:
List<User> forId = daoObj.findForId(3);
动态SQL语句
概念
所谓动态语句,就是可变化的SQL语句.这些变化条件可以是if判断,也可以是foreach循环来达成的.
准备 导入slf4j日志记录Jar包
推荐使用一个能够日志记录的jar包’slf4j’
它最重要的功能是能够输出实时地显示sql执行语句
这样,我们就能够更明确的看到,在动态SQL语句模式下,执行时的sql动态语句到底是什么样子,能够更好地帮助我们排错
格式:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>
WHERE条件标签
在Mybatis中,可以用过Mybatis标签快速替代传统的WHERE条件语句.
它需要用到where标签.主要作用是替代’where 1=1’
格式:
<选择一个增删改查标签 id="Dao接口的方法名" parameterType="Dao接口方法中的形参类型" resultType="Dao接口方法中的返回值">
SQL语句 <where> 用于拼接条件的sql语句 <where>
</选择一个增删改查标签>
</mapper>
列如:
<select id="whereTest" parameterType="cn.mybatisday2.domin.User" resultType="cn.mybatisday2.domin.User">
SELECT * FROM userinfo <where> id=#{id} AND username=#{username} </where>
</select>
if条件语句
if条件语句是Mybatis中,动态SQL语句的一种.
既然是’if’,那就是条件判断.
它的主要作用在于,根据一个条件是否成立,来决定是否插入一个sql语句.
格式:
<选择一个增删改查标签 id="Dao接口的方法名" parameterType="Dao接口方法中的形参类型" resultType="Dao接口方法中的返回值">
SQL语句
<if test="自定义条件一">
定义假如条件成立后要插入的SQL语句
</if>
<if test="自定义条件二">
定义假如条件成立后要插入的SQL语句
</if>
<if test="自定义条件三">
定义假如条件成立后要插入的SQL语句
</if>
<if test="自定义条件四">
定义假如条件成立后要插入的SQL语句
</if>
</选择一个增删改查标签>
</mapper>
列如:
<select id="findForWhere" parameterType="cn.mybatisday2.domin.User" resultType="cn.mybatisday2.domin.User">
SELECT * FROM userinfo
<where>
<if test="id!=0"><!-- 判断:你传入的'id'值不为0,那么就添加下面这行sql条件语句 -->
AND id=#{id}
</if>
<if test="username!=null"><!-- 判断:如果你传入的'username'值不为空,那么就在sql语句中添加下面这个条件语句 -->
AND username=#{username}
</if>
</where>
</select>
foreach循环拼接语句
foreach标签的主要作用用于循环地拼接sql语句.
但实际上,foreach还会根据你在service层传入的参数数量,来自动地增加SQL语句中的参数充填位置
.
foreach标签的属性含义如下:
•collection:代表要遍历的集合元素,注意编写时不要写#{}
•open:代表固定语句的开始部分
•close:代表固定语句的结束部分
•item:代表遍历集合的每个元素,生成的变量名
•sperator:代表参数充填处的分隔符
格式:
<选择一个增删改查标签 id="Dao接口的方法名" parameterType="Dao接口方法中的形参类型" resultType="Dao接口方法中的返回值">
SQL语句
<foreach collection="Service层中用于传递参数的集合类型,如用list集合传递参数,则写为list" open="固定拼接语句的开始部分" close="固定拼接语句的结束部分" item="用于充填参数的元素名" separator="参数充填出处的分隔符">
#{id}
</foreach>
</选择一个增删改查标签>
</mapper>
列如:
<!-- 通过多个id进行多次查询 [动态SQL语句]要用到foreach-->
<select id="findForIds" parameterType="list" resultType="cn.mybatisday2.domin.User">
SELECT * FROM userinfo
<where>
<!-- SELECT * FROM userinfo WHERE id IN(?); 其中,IN查询语句的括号内可以充填多个参数,如:WHERE id IN(?,?,?,?)
所以此处的foreach循环,是根据参入的集合有多少个数值元素,来视为有多少个问好'?',并把集合中的数值元素来充填到问号上.
-->
<foreach collection="list" open="id IN(" close=")" item="id" separator=",">
#{id}
</foreach>
</where>
</select>
分页查询
我们可以通过Mybatis进行分页查询,这一过程相比传统方式会非常省事,也不需要你用Bean实体类来封装分页查询的数据.
如果你有什么不懂的,可以访问他们的官网来查看帮助信息:https://pagehelper.github.io/
准备一:导入插件
实际上,这一功能依赖于Mybatis中的一个插件,那就是PageHelper
<!-- 导入分页查询插件的Jar包 'PageHelper' -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<!-- 此处为高版本的5.1.2 因此在sqlMapConfig.xml中的配置格式会同低版本的不同 -->
<version>5.1.2</version>
</dependency>
准备二:编辑核心配置文件
导入插件后,我们需要在核心配置文件’sqlMapConfig.xml’进行配置,以便能够应用到该插件.
注意:
一.如果插件5版本以上跟5版本以后的配置方式会有区别
这里是以5以上版本的配置格式来举例
二.PageHelPer分页插件必须写在plugins围堵标签内
三: plugins围堵标签必须在configuration围堵标签内,且plugins围堵标签的位置顺序必须在environments(用于配置数据源环境的标签)标签的上面
格式:
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="helperDialect" value="mysql"/>
<property name="reasonable" value="true"/>
</plugin>
</plugins>
优化方式查询(推荐)
目的:
以前的用法中,参数是恒定的.现在的用法中,是实时更新的参数 .也就是说,每次执行dao层的查询方法,都会依照当前的参数来执行
就是说 :如果本次没有被消费,可以下次被别的请求消费,同时又不会让分页查询的参数发生变动,这可以避免一些不可预测的,业务逻辑上的bug
步骤一:定义查询参数并调用Dao层方法
格式:PageInfo 自定义PageInfo对象名 = PageHelper.startPage(当前页, 欲显示的每页数量).doSelectPageInfo(()->Dao层对象.方法名(要传递的方法参数));
列如:
PageInfo pageResultObj = PageHelper.startPage(pageObj.getCurrentPage(), pageObj.getPageSize()).doSelectPageInfo(()->cid.findPage(pageObj.getQueryString()));
步骤二:获取查询结果
格式:自定义PageInfo对象名.getList();
列如:
pageResultObj.getList()
扩展:方法
一.getTotal
用于获取总数据量(非本页查询的,是所有页的数据条目数量)
传统方式查询
应用一:进行分页查询
步骤一.实例化Dao接口对象之
格式:Dao接口类名 自定义Dao接口实例化对象名 = 自定义sqlSession对象名.getMapper(Dao接口类名.class);
列如:
UserDao mapper = sqlSessionObj.getMapper(UserDao.class);
步骤二(重要).设置分页数据
格式:PageHelper.startPage(自定义要查询的页码,自定义每页显示多少条数据);
列如:
PageHelper.startPage(1,6 );
步骤三.执行SQL语句,并返回分页查询结果
格式:List<实体类名> 自定义list集合接收结果名 = 自定义Dao接口实例化对象名.Dao接口方法名();
列如:
List<User> listResult = mapper.findPage();
应用二:获取分页详情
步骤一:通过返回的list集合对象来获取分页详情对象
格式:PageInfo<实体类名> 自定义分页详情对象名 = new PageInfo<实体类名>(自定义list集合接收结果);
列如:
PageInfo<User> pageInfo = new PageInfo<User>(listResult);
步骤二:根据方法来获取不同的分页详情
重要方法:获取分页数据
page对象同样可以获取当页的查询数据
方法为:getResult();
方法一:获取总页数(相对于你设置的每页显示的数量)
自定义分页详情对象名.getPages();
方法二:获取总条数
自定义分页详情对象名.getTotal();
方法三:获取当前页数
自定义分页详情对象名.getPageNum();
方法四:获取每页显示的数量(也就是你在此前设置的pageSize值)
自定义分页详情对象名.getPageSize();
方法五:获取上一页的页码
自定义分页详情对象名.getPrePage();
方法六:获取下一页的页码
自定义分页详情对象名.getNextPage();
方法七:判断当前页是否为第一页
自定义分页详情对象名.isIsFirstPage();
方法八:判断当页是否是是最后一页
自定义分页详情对象名.isIsLastPage();