接口代理实现dao层代码
目标
通过配置让mybatis帮我们创建dao接口的实现类对象。
介绍
采用 Mybatis 的代理开发方式实现 dao层的开发,这种方式是我们后面进入企业的主流。
接口代理方式只需要程序员编写dao 接口(后期叫做mapper接口),由Mybatis 框架根据接口定义创建接口的动态代理对象。
需要遵循以下规范:
1) 映射文件中的namespace与dao接口的全类名相同
2) 映射文件中的增删改查标签的id属性与dao接口的方法名相同
3) 映射文件中的增删改查标签的parameterType属性与dao接口中方法的参数类型匹配
4) 映射文件中的增删改查标签的resultType属性与dao接口中方法的返回值类型匹配
记忆方式:以后映射文件就是描述mapper/dao接口的文件
代码实现
第一步:创建数据库表
1 | CREATE TABLE `user`( |
第二步:导入jar包
第三步:创建实体类
1 | package cn.itcast.domain; |
第四步:创建dao接口
1 | package cn.itcast.dao; |
第四步:创建映射文件
在src或者resource目录创建映射文件,名字叫UserMapper.xml
1 |
|
第五步:创建主配置文件
在src或者resources目录创建主配置文件,名字叫mybatis-config.xml
settings、typeAliases、properties配置参考第一天的配置
1 |
|
第五步:编写测试方法
注意:
使用的是org.apache.ibatis包下的Resources类
1 |
|
小结
接口代理方式让我们只编写接口即可,而实现类对象由MyBatis生成
实现规则
1) 映射文件中的namespace与dao接口的全类名相同
2) 映射文件中的增删改查标签的id属性与dao接口的方法名相同
3) 映射文件中的增删改查标签的parameterType属性与dao接口中方法的参数类型匹配
4) 映射文件中的增删改查标签的resultType属性与dao接口中方法的返回值类型匹配
动态SQL
介绍
Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。比如以下需求
findbyCondition(User user)
:根据传入的user对象进行查询,将不为空的属性作为查询条件update(User user)
:根据传入的user对象进行更新,将不为空的属性更新到数据库insert(User user)
:根据传入的user对象进行新增,将不为空的属性插入到数据库
像上面的场景,程序运行时的不同条件产生不同的SQL,这就用到了动态SQL。 动态SQL是Mybatis的强大特性之一。它的主要作用是通过Mybatis提供的标签实现sql的动态拼装。
Mybatis3之后,需要了解的动态SQL标签仅仅只有下面几个:
if 用于条件判断
where
foreach 用于循环遍历
sql片段
where标签
作用:代替where关键字,生成SQL的时候会判断是否有查询条件,如果有就会拼接where关键字,没有则不会拼接
if标签
格式和注意事项
注意事项:if标签中的test中获取值时不能出现#{},逻辑判断用and 和or 不能用&& 和 ||
1 | <where> |
需求
根据用户信息查询对应的数据
分析
用户信息有哪些不确定,所以方法的形参直接用实体类更方便,查询结果有多少不确定,所以返回值类型是集合。那么最终接口中需要定义的方法就是List<User> findByCondition(User condition);
实现步骤
第一步:映射文件中定义条件查询语句
1 | <select id="findByCondition" parameterType="user" resultType="user"> |
第二步:定义测试方法
1 |
|
生成的SQL语句
1 | select * from `user` WHERE password = ? |
foreach标签
作用
循环执行sql的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,2,5)。
格式
1 | <where> |
collection:代表要遍历的集合元素,注意编写时不要写#{}
如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了, map的key就是参数名
open:代表语句的开始部分
close:代表结束部分
item:代表遍历集合的每个元素,生成的变量名
sperator:代表分隔符
案例1:接口方法形参是List类型
第一步:UserDao中新增方法
1 | List<User> findByEmail1(List<String> emails); |
第二步:配置映射文件
1 | <select id="findByEmail" resultType="user" > |
第三步:编写测试方法
1 |
|
如果emails集合中有数据,控制台输出的SQL语句
1 | select * from `user` WHERE email in ( ? , ? , ? ) |
如果emails集合中没有数据,控制台输出的SQL语句
1 | select * from `user` |
案例2:接口方法形参是数组类型
第一步:UserDao中新增方法
1 | List<User> findByEmail2(String... emails); |
第二步:配置映射文件
1 | <select id="findByEmail2" resultType="user" > |
第三步:编写测试方法
1 |
|
SQL片段抽取
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的
1 | <!--抽取sql片段简化编写--> |
分页插件的使用
第一步:导分页jar包
第二步: 集成分页助手插件
在主配置文件的typeAliases标签后添加如下代码
1 | <plugins> |
第三步:添加查询全部功能
UserDao接口中新添加的方法
1 | List<User> findAll(); |
UserMapper中添加以下配置
1 | <select id="findAll" resultType="user"> |
第四步:测试类中使用分页
1 |
|
查看结果
1 | 总页数:3 |
分页的业务层代码
接口
1 | package cn.itcast.service; |
实现类
1 | package cn.itcast.service.impl; |
一对一查询
表关系
一对一关系中,表关系由任意一方维护,以人和身份证为例,一个人对应一个身份证,一个身份证对应一个人。本案例中由身份证表维护表关系
需求
查询所有的身份证,并且要将身份证对应的人也查询出来
实现步骤
第一步:建表
1 | DROP TABLE IF EXISTS `person`; |
第二步:创建实体类
Person 人类
1 | package cn.itcast.domain; |
Card 身份证类,因为需求是查询身份证,并且查询对应的人,所以应该是Card实体类中存放Perosn属性
1 | package cn.itcast.domain; |
第三步:创建Dao接口
1 | package cn.itcast.dao; |
第四步:创建映射文件
resultMap的分析与编写
在src或resources目录创建CardMapper.xml
1 |
|
第五步:主配置导入映射文件
在mybatis-config.xml中的mappers标签中引入CardMapper.xml
1 | <mappers> |
第六步:编写测试方法
1 |
|
小结
一对一查询,使用resultMap+association标签
一对多查询
表关系
一对多关系中,表关系由多的一方维护,以班级和学生为例,一个班级可以有多个学生,学生表应该维护表关系。
需求
查询所有班级信息,并且要将班级对应的学生信息也同时查询出来
实现步骤
第一步:建表
1 | DROP TABLE IF EXISTS `classes`; |
第二步:创建实体类
Student学生类
1 | package cn.itcast.domain; |
Classes班级类,因为需求是查询班级,以及对应的学生,所以应该是班级类中定义List表示一堆学生
1 | package cn.itcast.domain; |
第三步:创建Dao接口
1 | package cn.itcast.dao; |
第四步:创建映射文件
resultMap的分析与编写
在src或者resources目录下创建ClassesMapper.xml
1 |
|
第五步:主配置导入映射文件
在mybatis-config.xml中的mappers标签中引入ClassesMapper.xml
1 | <mappers> |
第六步:编写测试方法
1 |
|
小结
一对多查询,使用resultMap+collection标签
多对多关系
表关系
多对多关系中表关系由中间表维护,以学生和课程为例,一个学生对应多们课程,一个课程同时对应多个学生
需求
查询所有的学生,并且要将学生对应的课程也查询出来
实现步骤
第一步: 建表
1 | DROP TABLE IF EXISTS `classes`; |
第二步:创建实体类
Course 课程类
1 | package cn.itcast.domain; |
Student 学生类,学生类之前已经定义过了,只需要添加新的course属性即可。因为需求是查询学生信息,以及对应的课程,所以应该在学生类中定义List,表示一堆课程
1 | package cn.itcast.domain; |
第三步:创建Dao接口
1 | package cn.itcast.dao; |
第四步:创建映射文件
resultMap的分析与编写
在src或resources目录下创建StudentMapper.xml
1 |
|
第五步:主配置导入映射文件
在mybatis-config.xml中的mappers标签中引入StudentMapper.xml
1 | <mappers> |
第六步:编写测试方法
1 |
|
小结
多对多查询,使用resultMap+collection标签
多表查询总结
什么情况使用resultMap标签
情况1:如果查询的结果集的列名和实体类的属性名不匹配,就需要使用resultMap建立匹配规则
情况2:如果涉及到多表查询也需要使用resultMap标签,一对一查询用resultMap+association,一对多和多对多 resultMap+collection