java 框架

DAY03-mybatis

2020-04-24  本文已影响0人  建国同学

一、 mybatis步骤

  1. 新建表(查看mysql的编码:show variables like ‘%char%’)
  2. 新建 Maven 项目和添加依赖和插件
  3. 在资源目录下添加db.properties、mybatis-config.xml、log4j.properties 配置文件
  4. 编写实体类
  5. 编写Mapper xml 文件
  6. 编写MyBatisUti工具类获取session对象
  7. 编写测试类

二、 Mapper接口

之前存在的问题

使用Mapper接口

使用Mapper接口后,不存在DAO类,项目结构如下:

Mapper接口的原理

三、 MyBatis的参数处理

@Param注解

集合/数组参数

当传递一个 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 的文本处理器相似。
&gt : >
$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 &gt;= #{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.png
image.png

九、 关系概述

保存:页面的数据 ----> 使用 Java 对象封装 ---> 通过 MyBatis ---> 数据库表的数据
查询:数据库表的数据 ---> 通过 MyBatis ---> 封装成 Java 对象 ---> 页面展示数据

需要解决什么问题

怎么使用 Java 类设计来表示对象之间关系;
怎么使用数据库表设计来表示数据之间关系;
怎么通过 MyBatis 配置来映射上面两者(翻译)。

对象关系分类

泛化关系
实现关系
依赖关系
关联关系
聚合关系
组合关系

关联关系

A 对象依赖 B 对象,并且把 B 作为 A 的一个成员变量,则 A 和 B 存在关联关系。
在 UML 中依赖通常使用实线箭头表示。

十、单向多对一之保存

image.png

十一、 向多对一之额外SQL查询

image.png

十二、 单向多对一之多表查询

步骤:

额外SQL查询N+1问题

需求:查询所有员工及其对应部门。
假设在employee表中有N条数据,每一个员工都关联着一个不同的部门id。
当在查询所有员工时,就会发送 N+1 条语句。
1 条:SELECT * FROM employee;
N 条:SELECT * FROM department WHERE id = ?

使用resultMap处理结果集映射

image.png

十三、单向一对多之保存

需求:保存一个部门和两个员工,且这两个员工都是这个部门的。
建议集合对象直接 new 出来,避免空指针。


image.png

存在的问题:

遇到问题是保存子员工表中的员工数据没有部门 id。

解决:

在 many 放添加一个 Long 类型的 deptId,在保存部门之后把部门的 id 值设置到员工对象这个 deptId 属性再保存员工。

十四、单向一对多之额外SQL查询

需求:(根据id)查询部门,并把其部门的员工信息也查询出来。

存在的问题:

发现只能查询出部门信息,员工信息没有查询出来,怎么办?

  1. 手动额外发送SQL去传递该部门的id去查询员工出来,再把查询的员工手动存到该部门的的employees属性上;
  2. 使用 MyBatis 的额外SQL来完成。

使用collection发送额外SQL

image.png

十五、单向多对多之保存

需求:
保存两个学生和两个老师,且这两个老师都教了这个两个学生。

步骤:

十六、单向多对多之额外SQL查询

需求:
根据id查询学生,并查询其老师。

十七、单向多对多之删除

需求:
根据id删除学生。

上一篇 下一篇

猜你喜欢

热点阅读