一、 mybatis步骤
- 新建表(查看mysql的编码:show variables like ‘%char%’)
- 新建 Maven 项目和添加依赖和插件
- 在资源目录下添加db.properties、mybatis-config.xml、log4j.properties 配置文件
- 编写实体类
- 编写Mapper xml 文件
- 编写MyBatisUti工具类获取session对象
- 编写测试类
二、 Mapper接口
之前存在的问题
- namespace.id使用字符串填入查询的参数,容易编写错误
- 第二个参数的类型是Oeject所以不被检查传入的类型而容易出错
使用Mapper接口
使用Mapper接口后,不存在DAO类,项目结构如下:
- image.png
- mapper xml文件和mapper 类保持统一路径,这样编译之后它们的字节码就会在一个路径下
和 - XML 命名空间用其对应接口的全限定名;
-
Mapper 接口的方法名要和 Mapper XML 文件元素(select | update | delete | insert) id 值一样;
image.png - 方法的返回类型对应 SQL 元素中定义的 resultType / resultMap 类型;
- 方法的参数类型对应 SQL 元素中定义的 paramterType 类型
-
定义Mapper接口
image.png
Mapper接口的原理
-
通过打印接接口,发现打印的是:class com.sun.proxy.$Proxy5,底层使用的是动态代理(后面 Spring 再讲),生成 Mapper 接口的实现类。
-
接口是规范,实质做的实现还是要由实现类对象来做,而这个实现类不需要我们写,实现类对象也不由我们创建,这些都 MyBatis 使用动态代理帮我们做了;
我们只需提供 Mapper 接口对应 Mapper XML 文件,获取实现类对象的时候传入 Mapper 接口就可以了(不然 MyBatis 也不知道你要获取哪个 Mapper 接口的实现类对象);
至于实现类中操作方式底层还是和之前的一样,因为 Mapper XML 命名空间是使用 Mapper 接口的全限定名,方法名又与对应 XML 元素 id 一致,所以可以通过获取调用方法所在 Mapper 接口的权限名和方法名,拼接出 namespace + id,再配合调用方法的实参就可以像之前一样操作了。
三、 MyBatis的参数处理
@Param注解
- 使用@Param注解解决范式,解决接口只支持一个参数的情况
-
本质相当于构建一个Map对象,key为注解 @Param的值,value为参数的值。
image.png
集合/数组参数
当传递一个 List 对象或数组对象参数给 MyBatis 时,MyBatis 会自动把它包装到一个 Map 中,此时:
List 对象会以 list 作为 key,数组对象会以 array 作为 key,也可以使用注解 @Param 设置 key 名。
四、 MyBatis 的 # 和 $
1、相同点
都可以获取对象(Map 对象或者 JavaBean 对象)的信息。
2、不同点
使用 # 传递的参数会先转换为,无论传递是什么类型数据都会带一个单引号;
使用 $ 传递的参数,直接把值作为 SQL 语句的一部分;
使用 #支持把简单类型(八大基本数据类型及其包装类、String、BigDecimal 等等)参数作为值;
使用 $ 不支持把简单类型参数作为值;
使用 # 好比使用 PrepareStatement,没有 SQL 注入的问题,相对比较安全;
使用 $ 好比使用 Statement,可能会有 SQL 注入的问题,相对不安全。
总结
若需要作为 ORDER BY 或 GROUP BY 子句获取参数值使用 $;
若需要作为其它子句获取参数值使用 #。
五、动态SQL
动态SQL是MyBatis 的强大特性之一,解决了拼接 SQL 语句的痛苦
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。
> : >
$lt : <
六、动态SQL之if和where
这里test属性里取值是用$符号去取值,此时参数类型为BigDecimal类型,需要在接口形参加注解@Param
List<Employee> querByMinSalary(@Param("minSalary")BigDecimal minSalary);
<select id="querByMinSalary" resultType="Employee">
SELECT id, name, sn, salary, deptId FROM employee
<if test="minSalary != null">
WHERE salary >= #{minSalary}
</if>
</select>
七、动态SQL之set
set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,若里面条件都不成立,就会去除 SET 关键字。其用来解决更新时丢失数据的问题。
不完善的实现
<update id="update">
UPDATE employee
<if test="name != null">name = #{name},</if>
<if test="sn != null">sn = #{sn},</if>
<if test="salary != null">salary = #{salary},</if>
<if test="deptId != null">deptId = #{deptId},</if>
WHERE id = #{id}
</update>
问题:虽然可以解决更新丢失数据的问题,但会造成多逗号或者少逗号的问题(比如就第一个条件成立)
使用set元素实现
<update id="update">
UPDATE employee
<set>
<if test="name != null">name = #{name},</if>
<if test="sn != null">sn = #{sn},</if>
<if test="salary != null">salary = #{salary},</if>
<if test="deptId != null">deptId = #{deptId},</if>
</set>
WHERE id = #{id}
</update>
八、动态SQL之foreach
动态 SQL 的另外一个常用的操作需求是对一个集合进行遍历,通常是在构建 IN 条件语句的时候,这里就会使用到foreach元素。
image.pngimage.png
九、 关系概述
保存:页面的数据 ----> 使用 Java 对象封装 ---> 通过 MyBatis ---> 数据库表的数据
查询:数据库表的数据 ---> 通过 MyBatis ---> 封装成 Java 对象 ---> 页面展示数据
需要解决什么问题
怎么使用 Java 类设计来表示对象之间关系;
怎么使用数据库表设计来表示数据之间关系;
怎么通过 MyBatis 配置来映射上面两者(翻译)。
对象关系分类
泛化关系
实现关系
依赖关系
关联关系
聚合关系
组合关系
关联关系
A 对象依赖 B 对象,并且把 B 作为 A 的一个成员变量,则 A 和 B 存在关联关系。
在 UML 中依赖通常使用实线箭头表示。
-
按照导航性分:
1)、单向:只能从 A 通过属性导航到 B,B 不能导航到 A。
2)、双向:A 可以通过属性导航到 B,B 也可以通过属性导航到 A。 -
按照多重性分
一对一,一对多,多对一,多对多。 -
如何判断对象的关系
判断都是从对象的实例上面来看的;
判断关系需要根据对象的属性;
十、单向多对一之保存
image.png十一、 向多对一之额外SQL查询
image.png十二、 单向多对一之多表查询
步骤:
-
image.png
需求:查询所有员工及其对应部门。
image.png
额外SQL查询N+1问题
需求:查询所有员工及其对应部门。
假设在employee表中有N条数据,每一个员工都关联着一个不同的部门id。
当在查询所有员工时,就会发送 N+1 条语句。
1 条:SELECT * FROM employee;
N 条:SELECT * FROM department WHERE id = ?
使用resultMap处理结果集映射
image.png- image.png
十三、单向一对多之保存
需求:保存一个部门和两个员工,且这两个员工都是这个部门的。
建议集合对象直接 new 出来,避免空指针。
image.png
存在的问题:
遇到问题是保存子员工表中的员工数据没有部门 id。
解决:
在 many 放添加一个 Long 类型的 deptId,在保存部门之后把部门的 id 值设置到员工对象这个 deptId 属性再保存员工。
十四、单向一对多之额外SQL查询
需求:(根据id)查询部门,并把其部门的员工信息也查询出来。
存在的问题:
发现只能查询出部门信息,员工信息没有查询出来,怎么办?
- 手动额外发送SQL去传递该部门的id去查询员工出来,再把查询的员工手动存到该部门的的employees属性上;
- 使用 MyBatis 的额外SQL来完成。
使用collection发送额外SQL
image.png十五、单向多对多之保存
需求:
保存两个学生和两个老师,且这两个老师都教了这个两个学生。
步骤:
- image.png
-
插入时需要在中间表插入数据,以实现学生和教师的联系
image.png
十六、单向多对多之额外SQL查询
需求:
根据id查询学生,并查询其老师。
-
查询学生
image.png -
教师
image.png
十七、单向多对多之删除
需求:
根据id删除学生。
-
注意:要先删除中间表的联系 ,因为该表可能有外键约束
-
删除中间表的联系
image.png -
删除去除关系的学生
image.png
网友评论