1.Mybatis入门
1.1 Mybatis定义
MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。
MyBatis本是 Apache的一个开源项目iBatis,2010年这个项目由apache迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
在上面我们提到了两个词:一个是持久层,另一个是框架
- 持久层:指的是就是数据访问层(dao),是用来操作数据库的
- 框架:是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。在框架的基础上进行软件开发更加高效、规范、通用、可拓展
1.2 入门程序分析
现在使用Mybatis操作数据库,就是在Mybatis中编写SQL查询代码,发送给数据库执行,数据库执行后返回结果
Mybatis会把数据库执行的查询结果,使用实体类封装起来(一行记录对应一个实体类对象)
1.3 入门程序实现步骤
- 准备工作(创建springboot工程、数据库表user、实体类User)
- 在pom.xml中引入Mybatis的相关依赖,
- yml文件中配置Mybatis(数据库连接信息)
- mapper层编写SQL语句(注解/XML)
1.3 解决mapper层编写sql语句不提醒
1.4 JDBC
1.4.1 介绍
通过Mybatis可以很方便的进行数据库的访问操作。但是大家要明白,其实java语言操作数据库呢,只能通过一种方式:使用sun公司提供的 JDBC 规范
Mybatis框架,就是对原始的JDBC程序(Java语言操作关系型数据库的一套API)的封装
本质:
sun公司官方定义的一套操作所有关系型数据库的规范,即接口。
各个数据库厂商去实现这套接口,提供数据库驱动jar包。
我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
1.4.2 代码
下面我们看看原始的JDBC程序是如何操作数据库的。操作步骤如下:
- 注册驱动
- 获取连接对象
- 执行SQL语句,返回执行结果
- 处理执行结果
- 释放资源
在pom.xml文件中已引入MySQL驱动依赖,我们直接编写JDBC代码即可
JDBC具体代码实现:
1 | import com.itheima.pojo.User; |
DriverManager(类):数据库驱动管理类。
作用:
注册驱动
创建java代码和数据库之间的连接,即获取Connection对象
Connection(接口):建立数据库连接的对象
- 作用:用于建立java程序和数据库之间的连接
Statement(接口): 数据库操作对象(执行SQL语句的对象)。
- 作用:用于向数据库发送sql语句
ResultSet(接口):结果集对象(一张虚拟表)
- 作用:sql查询语句的执行结果会封装在ResultSet中
通过上述代码,我们看到直接基于JDBC程序来操作数据库,代码实现非常繁琐,所以在项目开发中,我们很少使用。 在项目开发中,通常会使用Mybatis这类的高级技术来操作数据库,从而简化数据库操作、提高开发效率
1.4.3 问题分析
原始的JDBC程序,存在以下几点问题:
- 数据库链接的四要素(驱动、链接、用户名、密码)全部硬编码在java代码中
- 查询结果的解析及封装非常繁琐
- 每一次查询数据库都需要获取连接,操作完毕后释放连接, 资源浪费, 性能降低
1.4.4 mybatis优化点
分析了JDBC的缺点之后,我们再来看一下在mybatis中,是如何解决这些问题的:
数据库连接四要素(驱动、链接、用户名、密码),都配置在springboot默认的配置文件 application.properties中
查询结果的解析及封装,由mybatis自动完成映射封装,我们无需关注
在mybatis中使用了数据库连接池(Springboot默认Hikari追光者)技术,从而避免了频繁的创建连接、销毁连接而带来的资源浪费。
1.5 数据库连接池(四种)
1.5.1 介绍
没有使用数据库连接池:
- 客户端执行SQL语句:要先创建一个新的连接对象,然后执行SQL语句,SQL语句执行后又需要关闭连接对象从而释放资源,每次执行SQL时都需要创建连接、销毁链接,这种频繁的重复创建销毁的过程是比较耗费计算机的性能。
- 程序在启动时,会在数据库连接池(容器)中,创建一定数量的Connection对象
允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个
- 客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以复用)
释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏
- 客户端获取到Connection对象了,但是Connection对象并没有去访问数据库(处于空闲),数据库连接池发现Connection对象的空闲时间 > 连接池中预设的最大空闲时间,此时数据库连接池就会自动释放掉这个连接对象
数据库连接池的好处:
- 资源重用
- 提升系统响应速度
- 避免数据库连接遗漏
1.5.2 四种连接池
常见的数据库连接池:
- C3P0
- DBCP
- Druid
- Hikari (springboot默认)
现在使用更多的是:Hikari、Druid (性能更优越)
Hikari(追光者) [默认的连接池]
Druid(德鲁伊)
Druid连接池是阿里巴巴开源的数据库连接池项目
功能强大,性能优秀,是Java语言最好的数据库连接池之一
1.5.3 更换连接池
把默认的数据库连接池切换为Druid数据库连接池,只需要完成以下两步操作即可:
参考官方地址:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter
1.在pom.xml文件中引入依赖
1 | <dependency> |
2.在配置文件中引入数据库连接配置(2种方式)
1 | 方式1:(datasource后面加druid) |
1.6 lombok(编译阶段)
1.6.1 介绍
Lombok是一个实用的Java类库,可以通过简单的注解来简化和消除一些必须有但显得很臃肿的Java代码
通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,并可以自动化生成日志变量,简化java开发、提高效率
注解 | 作用 |
---|---|
@Getter/@Setter | 为所有的属性提供get/set方法 |
@ToString | 为类自动生成易阅读的 toString 方法 |
@EqualsAndHashCode | 为类提供拥有的非静态字段自动重写 equals 方法和 hashCode 方法 |
@Data | 提供了更综合的生成代码功能(@Getter + @Setter + @ToString + @EqualsAndHashCode) 集成了前四个注解 |
@NoArgsConstructor | 为实体类生成无参的构造器方法 |
@AllArgsConstructor | 为实体类生成除了static修饰的字段之外带有各参数的构造器方法。 |
1.6.2 使用步骤
第1步:在pom.xml文件中引入依赖
1 | <!-- 在springboot的父工程中,已经集成了lombok并指定了版本号,故当前引入依赖时不需要指定version --> |
第2步:在实体类上添加注解
1 | import lombok.Data; |
2.Mybatis基础操作
2.1 新增(@Insert)
2.2 删除(@Delete)
2.3 查询(@Selete)
2.4 修改(@Update)
3.Mybatis两种书写sql语句的形式
3.1 mapper层注解
3.2 xml映射文件
3.2.1 创建xml文件
- 整体图
创建位置:必须要和mapper层保持同一个包级别和同名(==同包同名==)
命名规则:要保证mapper的namespacce和mapper同全路径名,四大类语句的id要和方法名一致,resultType要和方法返回值(最里面的)一致
4.动态sql(在xml映射文件)
4.1 if
4.1.1 作用
用于判断条件是否成立 –如果条件为true就拼接sql
4.1.2 使用位置
4.2 where
4.2.1 作用
1.在子元素有内容的情况下插入where子句
2.自动去除子句开头的and/or
4.2.2 使用位置
4.3 set
4.3.1 作用
1.动态的在行首插入set关键字
2.自动去除额外的逗号
4.3.2 使用位置
4.4 foreach
4.4.1 作用
循环的时候批量处理一部分数据
4.4.2 使用位置
4.5 sql和include
4.5.1 作用
将一些固定的(重复的/相同的)sql提取出来
4.5.2 使用位置
4.6 choose-when-otherwise
4.6.1 作用
类似于Java的Switch语句,可以实现选择
4.6.2 使用位置
4.7 trim
4.7.1 作用
生成sql语句的时候,在前后添加自定义的字符串
4.7.2 使用位置
prefix:加前缀
prefixOverrides:要覆盖的前缀
suffix:加后缀
suffixOverrides:要覆盖的后缀
4.8 bind
4.8.1 作用
可以将表达式结果/特定内容绑定到一个变量,这个变量可以在sql语句中使用【类似于参数宏定义】
4.8.2 使用位置
5.mybatis日志输出
在Mybatis当中我们可以借助日志,查看到sql语句的执行、执行传递的参数以及执行结果。具体操作如下:
- 打开application.properties文件
- 开启mybatis的日志,并指定输出到控制台
1 | #指定mybatis输出日志的位置, 输出控制台 |
开启日志之后,我们再次运行单元测试,可以看到在控制台中,输出了以下的SQL语句信息:
但是我们发现输出的SQL语句:delete from emp where id = ?,我们输入的参数16并没有在后面拼接,id的值是使用?进行占位。那这种SQL语句我们称为预编译SQL
6.预编译SQL
mybatis中mapper层的写法就是预编译sql,传入参数放入的形式
预编译SQL有两个优势:
性能更高
更安全(防止SQL注入)
7.参数占位符
如果mapper接口方法形参只有一个普通类型的参数,#{…} 里面的属性名可以随便写
8.数据封装(mysql列名和实体类属性名不一致)
8.1 出现场景
8.2 三种解决方案
1. mapper层sql语句内起别名
2.mapper层方法上添加@Results和@Result注解手动映射
3.yml配置文件打开驼峰命名(推荐)
9.#{}和${}区别
#{}表达式为OGNL表达式
${}表达式为EL表达式
1)相同:都可以获取对象的信息。
(2)#{ }
执行SQL时,会将#{ }替换为?,生成预编译SQL,会自动设置参数值,防止SQL注入
使用时机:参数传递,都使用#{ }
(3)${ }
拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题
使用时机:如果对表名、列表进行动态设置时使用【东林微课堂创建每个月赛季表】
(4)#{ } 只能操作跟数据字表字段相关的列值,跟列值无关的只能用${ }
(5)#{ } 底层使用的是PreparedStatement,${ } 底层使用的是 Statement