Mybatis
1. Mybatis入门
1.1 Mybatis的介绍
-
MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。
-
MyBatis本是 Apache的一个开源项目iBatis, 2010年这个项目由apache迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
-
官网:MyBatis中文网
-
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
1.2 Mybatis的入门程序
-
步骤:
- 准备工作(创建springboot工程,数据库表user,实体类user,属性类型建议使用包装类)
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
- 引入Mybatis的相关依赖,配置Mybatis(数据库的链接信息)
- 2.1引入相关依赖
- 2.2链接数据库在application.properties中进行配置
- 编写SQL语句(注解/XML)
- 先定义一个持久层(DAO)的接口
- 一般java程序编写的实体类的参数名和数据库查询到的信息名对应,这样就可以自动封装
1.2.2一些错误的解决方案
- 当出现无法自动装配。找不到 ‘UserMapper’ 类型的 Bean。
- 因为对于有些是接口,通过添加Mapper注解是在程序运行时才会创建这个对象
- 解决方案:
@Autowired(required = false)
-
@Autowired(required=true):当使用@Autowired注解的时候,其实默认就是@Autowired(required=true),表示注入的时候,该bean必须存在,否则就会注入失败。
-
@Autowired(required=false):表示忽略当前要注入的bean,如果有直接注入,没有跳过,不会报错。
- 要注意mybatis与jdk的版本兼容关系,否则会保存
1.3 配置SQL提示
- 既可以提示报错,又可以提示SQL语句
- 第一次进行配置后,还没有与数据库建立连接,不识别表信息,要在IDEA中配置Mysql数据库连接
- 步骤总结:
- 先创建模块,并勾选好所需要的框架,并且要注意maven和jdk版本的适应情况,否则运行可能会出错
- 在resources包下的properties文件下对数据库进行连接,并且注意数据库连接的四要素:1.数据库的驱动类名称 **2.**数据库的url **3.**数据库的操作者 **4.**连接数据的密码
- 根据数据库表中的字段创建简单的对象,只需要实现get,set,构造,toString方法即可
- 再创建接口用来接收从数据库获取到的对象,通过 @Mapper和@SQL语句的注解来映射,通过@Mapper注解当程序运行时,会自动创建该接口的实现类,并放在IOC容器中管理,在接口创建方法并且添加相关SQL操作的注解
- 在到所需要的区域将数据展现出来
1.4 JDBC
- JDBC就是使用JAVA语言操作关系型数据库的一套API,接口
- 各个数据库厂商去实现这套接口,提供数据库驱动jar包
- 我们可以使用这套(JDBC)编程,真正执行的代码是驱动jar包中的实现类
-
mybatis框架与JDBC的区别:
-
对于数据库的连接来说,使用JDBC是使用硬编码,代码是写死的,而使用mybatis是在application.properties中进行配置,修改所需要的数据库连接很方便,只需要直接操作配置文件就可以
-
在JDBC中解析结果很麻烦,当解析完之后,要将一个个字段手动封装到对象中,当字段过多时,也不方便操作,而对于mybatis来说,会自动将结果封装到对象中。
-
对于JDBC来说获取数据库的连接,需要频繁的创建Connection对象,并且释放该资源,这样会导致资源浪费和性能降低,而对于mybatis来说,通过spring.datasource前缀来配置数据库连接信息,当使用该连接时,spring底层会自动采用数据库连接池技术来统一分配,管理这些连接,每一次执行SQL语句时,只需要从连接池中获取连接来完成,当执行完之后,会将连接归还连接池
-
1.5 数据库连接池
-
数据库连接池是个容器,负责分配,管理数据库连接(Connection)
-
它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个
-
当数据库的空闲时间(没有对数据库进行访问)超过预留的最大空闲时间时就会将连接归还给连接池,来避免因为没有释放连接而引起的数据库连接遗漏,
-
实现数据库连接池:
-
标准接口:DataSource
-
功能:获取连接
-
常见的连接池:
- springboot自带的连接池:Hikari(默认的)
- Druid(德鲁伊)
- Druid连接池是阿里巴巴开源的数据库连接池项目
- 功能强大,性能优秀,是Java语言最好的数据库连接池之一
-
-
切换连接池:
-
切换Druid数据库连接池
-
在配置文件中添加相关依赖,注意spring版本,对于spring2是下面这样配置依赖
-
对应spring3依赖配置
-
-
在application.properties文件中配置数据库的连接信息。两种都可以
-
-
1.6 lombok工具包
- 对于之前创建的实体类,过于臃肿,为了解决而引出lombok,只需要通过注解来完成@Data
- Lombok的介绍:
- Lombok是一个实用的java类库,能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,并可以自动化生成日志变量,简化java开发、提高效率。
注解 | 作用 |
---|---|
@Getter/Setter | 为所有的属性提供get/set方法 |
@ToString | 会给类自动生成易阅读的 toString 方法 |
@EqualsAndHashCode | 根据类所拥有的非静态字段自动重写 equals 方法和 hashCode 方法 |
@Data | 提供了更综合的生成代码功能(@Getter + @Setter + @ToString + @EqualsAndHashCode) |
@NoArgsConstructor | 为实体类生成无参的构造器方法 |
@AllArgsConstructor | 为实体类生成除了static修饰的字段之外带有各参数的构造器方法。 |
-
Lombok的依赖引入:
2. Mybatis的基础操作
- 以黑马程序员javaweb提供的资料中的页面原型来完成该项目
2.1 准备工作
- 准备数据库表emp
- 创建一个springboot工程,选中引入的起步依赖(mybatis,mysql驱动,lombok)
- 在application.properties中引入数据库连接信息
- 准备创建实体类Emp(实体类属性采用驼峰命名)
- 准备Mapper接口EmpMapper
2.2 删除功能(预编译SQL)
- 为了避免静态的删除一条数据,在实际开发中应该采用动态删除
-
这样就可以通过方法的参数,动态的删除数据
-
一般来说删除操作的返回值是影响的行数,也就是int类型,也可以不需要
-
当我们需要查看删除的SQL语句时,就可以通过日志来查看,在mybatis中日志是默认关闭的
-
可以在application.properties中,打开mybatis的日志,并指定输出到控制台
- 这一段就是执行的SQL语句,其中的?是参数占位符,在下面的Parameters就是参数,会替代?
-
这一段代码就是预编译SQL
-
使用预编译SQL语句的优势
-
性能更高
-
SQL的执行顺序:
- 从JAVA程序传递的SQL语句,会先通过SQL语法检测,优化SQL,编译SQL,再执行SQL,为了提高效率,会将前三步缓存起来,当再次执行SQL语句时,会先检测缓存是否有已经编辑好的数据,如果有就直接执行SQL语句,如果没有则按照步骤实现
- 采用预编译之所以效率高:是因为预编译SQL语句的SQL语句都是同一个,参数用?替代了,这样预编译的SQL语句都会在缓存中,下次执行SQL语句,SQL语句是一样的,该SQL语句已经被缓存,这样就有可以直接编译SQL
-
-
防止SQL注入
- SQL注入是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法
-
-
当我们在mybatis使用**#{}**占位符的方法就可以采用预编译SQL
-
参数占位符:
2.3 增加功能(主键返回)
- 由于添加功能为了动态绑定,也要使用#{}来动态绑定,并且为了便捷,应该将方法参数定义为一个对象
-
注意:SQL语句中的参数名称要和下面emp的属性名一模一样
-
主键返回:
- 在数据添加成功后,需要获取插入数据库数据的主键
- 为了实现这个功能,需要添加@Options注解
-
注意:将获取到的主键封装到emp中的id属性中,所以属性名要对应
2.4 更新功能
- 一般更新分为两步:第一步通过查询获取网页的回旋,第二步通过主键ID进行更新
2.5.1 查询功能(根据ID查询)
-
当我们这样查询时
-
查询结果:
Emp(id=20, username=wzc2, password=123456, name=wzc2, age=null, gender=1, img=null, job=1, entrydate=2004-10-08, deptId=null, createTime=null, updateTime=null)
-
其中的deptId=null, createTime=null, updateTime=null,这就涉及到mybatis的数据封装
2.5.1.1数据封装
-
实体类属性名和数据库表查询返回的字段名一样,mybatis会自动封装
-
实体类属性名和数据库表查询返回的字段名不一样,mybatis不会自动封装
-
解决方案:方案三最常用
-
给字段取别名,让别名与实体类属性名一致
-
- 方案二:通过@Results,@Result注解手动映射封装
-
方案三:开启mybatis的驼峰命名自动映射的开关:下划线命名的会自动封装到驼峰命名属性名中例:dept_id=deptId
-
要在application.properties中配置的
-
2.5.2 查询功能(条件查询)
- 方法一:用${}拼接,但是可以产生SQL注入
- 方法二:用concat函数拼接sql语句
2.6 XML映射文件
-
规范:
- XML映射文件的名称与Mapper接口名称一致,也就是一份接口对应一份XML文件,并且将XML映射文件和Mapper接口放置在相同包下,但是对于maven项目来说,java文件是放在java包下面的,配置文件是放在resources包下面的因此要这样解决(同包同名)
-
XML映射文件的namespace属性与Mapper接口全限定名一致(com.itheima.mapper.EmpMapper)
-
XML映射文件中的SQL语句的id与Mapper接口中方法名一致,并保持返回类型一致
-
注意:
-
在创建包的时候不能使用.进行分隔,要使用/进行分隔
-
XML都有固定的约束,这个是固定的,不需要记忆
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
-
最后XML文件的内容:
- 之所以XML映射文件要按照这三步,是因为,XML映射与注解不一样,XML映射与方法分开了,当调用list方法时,会先查找namespace属性值与list方法所在接口的全类名相同的的标签,再调用里面与方法名相同的id所关联的SQL语句
- 总结:
- 先找到与接口全类名相同的namespace的标签
- 再找到id与方法名相同的SQL语句并执行
- 这样就可以绑定所对应的操作
3. 动态SQL
-
随着用户输入或外部条件变化而变化的SQL语句,我们称为动态SQL
-
例如:查询信息时,可以只根据一条信息动态查询语句
-
mybatis提供了条件拼接语句if
-
对应动态SQL语句最好使用XML映射,不要使用注解来完成
3.1 if,where,set标签
-
:用于判断条件是否成立。使test属性进行条件判断,如果条件为true,则拼接SQL。
-
当使用普通where条件判断时,上一条语句中的and和or有时候会造成异常
-
因此要使用标签进行,where标签的作用:
- 通过判断该标签里面的test是否成立来决定是否生成where
- 可以根据条件判断,自动删除and或者or
-
对应更新语句,普通的set语句,当其中一条语句成立时,会在结尾有逗号(,)这样会导致异常
-
因此要使用标签替代set,其作用:
- 会去除掉字段之后多余的逗号(,)
3.2 foreach标签
3.3 sql,include标签
-
和标签是配套使用的
-
使用:当有多条重复使用的sql语句时,可以用标签将其抽取出来,再使用标签将其放回原处使用
-
再查询所有字段时,不建议使用*,而是建议将所有字段全部罗列出来
-
现将SQL语句抽取出来,并添加id
-
再在原有的地方引用这个