MyBatis基本操作及使用

什么是MyBatis?
MyBatis是⼀款优秀的 持久层 框架,⽤于简化JDBC的开发。
MyBatis本是 Apache的⼀个开源项⽬iBatis,2010年这个项⽬由apache迁移到了google code,并
且改名为MyBatis 。2013年11⽉迁移到Github.
在上⾯我们提到⼀个词:持久层
持久层:指的就是持久化操作的层, 通常指数据访问层(dao), 是⽤来操作数据库的.
简单来说 MyBatis 是更简单完成程序和数据库交互的框架,也就是更简单的操作和读取数据库⼯具
接下来,我们就通过⼀个⼊⻔程序,让⼤家感受⼀下通过Mybatis如何来操作数据库
MyBatis⼊⻔
Mybatis操作数据库的步骤:
1. 准备⼯作(创建springboot⼯程、数据库表准备、实体类)
Mybatis 是⼀个持久层框架, 具体的数据存储和数据操作还是在MySQL中操作的, 所以需要添加
MySQL驱动
项⽬⼯程创建完成后,⾃动在pom.xml⽂件中,导⼊Mybatis依赖和MySQL驱动依赖
版本会随着SpringBoot 版本发⽣变化
SpringBoot 3.X对⽤MyBatis版本为3.X
2. 引⼊Mybatis的相关依赖,配置Mybatis(数据库连接信息)

Mybatis中要连接数据库,需要数据库相关参数配置
MySQL驱动类
登录名
密码
数据库连接字符串
yml配置mybatis连接数据库配置
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

如果密码是纯数字则需要加单引号

写持久层代码
在项⽬中, 创建持久层接⼝UserInfoMapper
Mybatis的持久层接⼝规范⼀般都叫 XxxMapper
@Mapper注解:表⽰是MyBatis中的Mapper接⼝
程序运⾏时, 框架会⾃动⽣成接⼝的实现类对象(代理对象),并给交Spring的IOC容器管理
@Select注解:代表的就是select查询,也就是注解对应⽅法的具体实现内容.在select中写入SQL语句
进行方法测试

测试类上添加了注解 @SpringBootTest,该测试类在运⾏时,就会⾃动加载Spring的运⾏环境.
我们通过@Autowired这个注解, 注⼊我们要测试的类, 就可以开始进⾏测试了
MyBatis注解基本操作      
打印日志 
在Mybatis当中我们可以借助⽇志, 查看到sql语句的执⾏、执⾏传递的参数以及执⾏结果
在在yml文件中进⾏配置即可
mybatis:
  configuration: # 配置打印 MyBatis ⽇志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
参数传递
需求: 查找id=4的⽤⼾,对应的SQL就是: select * from userinfo where id=4
@Select("select username, `password`, age, gender, phone from userinfo where
id= 4 ")
UserInfo queryById ();
但是这样的话, 只能查找id=4 的数据, 所以SQL语句中的id值不能写成固定数值,需要变为动态的数值
解决⽅案:在queryById⽅法中添加⼀个参数(id),将⽅法中的参数,传给SQL语句
使⽤ #{} 的⽅式获取⽅法中的参数

如果mapper接⼝⽅法形参只有⼀个普通类型的参数,#{…} ⾥⾯的属性名可以随便写,如:#{id}、#{value}。建议和参数名保持⼀致

返回主键
Insert 语句默认返回的是 受影响的⾏数
但有些情况下, 数据插⼊之后, 还需要有后续的关联操作, 需要获取到新插⼊数据的id
⽐如订单系统
当我们下完订单之后, 需要通知物流系统, 库存系统, 结算系统等, 这时候就需要拿到订单ID
如果想要拿到⾃增id, 需要在Mapper接⼝的⽅法上添加⼀个Options的注解
useGeneratedKeys:这会令 MyBatis 使⽤ JDBC 的 getGeneratedKeys ⽅法来取出由数据库内
部⽣成的主键(⽐如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的⾃动递增字
段),默认值:false.
keyProperty:指定能够唯⼀识别对象的属性,MyBatis 会使⽤ getGeneratedKeys 的返回值或
insert 语句的 selectKey ⼦元素设置它的值,默认值:未设置(unset)
@Options(useGeneratedKeys = true,keyProperty = "id")
注意: 设置 useGeneratedKeys=true 之后, ⽅法返回值依然是受影响的⾏数, ⾃增 id 会设置在上
keyProperty 指定的属性中
映射关系
当⾃动映射查询结果时,MyBatis 会获取结果中返回的列名并在 Java 类中查找相同名字的属性(忽略⼤⼩写)。 这意味着如果发现了 ID 列和 id 属性,MyBatis 会将列 ID 的值赋给 id 属性,数据库中的字段名与Java属性名字不相同
映射关系的解决办法:
结果映射
如果其他SQL, 也希望可以复⽤这个映射关系, 可以给这个Results定义⼀个名称
使⽤ id 属性给该 Results 定义别名, 使⽤ @ResultMap 注解来复⽤其他定义的 ResultMap
2. 开启驼峰命名
通常数据库列使⽤蛇形命名法进⾏命名(下划线分割各个单词), ⽽ Java 属性⼀般遵循驼峰命名法约定.
为了在这两种命名⽅式之间启⽤⾃动映射,需要将 mapUnderscoreToCamelCase 设置为 true。在yml中进行配置即可
mybatis:
   configuration:
    map-underscore-to-camel-case: true
MyBatis XML配置⽂件以及基本操作
Mybatis的开发有两种⽅式:
1. 注解
2. XML
上⾯学习了注解的⽅式, 接下来我们学习XML的⽅式
使⽤Mybatis的注解⽅式,主要是来完成⼀些简单的增删改查功能. 如果需要实现复杂的SQL功能,建议使⽤XML来配置映射语句,也就是将SQL语句写在XML配置⽂件中.
MyBatis XML的⽅式需要以下两步:
1. 配置数据库连接字符串和MyBatis

此步骤需要进⾏两项设置,数据库连接字符串设置和 MyBatis 的 XML ⽂件配置

mybatis:

  mapper-locations: classpath:mapper/**Mapper.xml

2. 写持久层代码

1.添加 mapper 接⼝
2.添加 UserInfoXMLMapper.xml
数据持久成的实现,MyBatis 的固定 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" >
< mapper namespace = "com.example.demo.mapper.UserInfoMapper" >
</ mapper >
创建UserInfoXMLMapper.xml, 路径参考yml中的配置
以下是对以上标签的说明:
<mapper> 标签:需要指定 namespace 属性,表⽰命名空间,值为 mapper 接⼝的全限定
名,包括全包名.类名。
<select> 查询标签:是⽤来执⾏数据库的查询操作的:
id :是和 Interface (接⼝)中定义的⽅法名称⼀样的,表⽰对接⼝的具体实现⽅法。
resultType :是返回的数据类型,也就是开头我们定义的实体类.
解决办法和注解类似:
1.  结果映射
2.  开启驼峰命名
解决办法和注解⼀样,接下来看下xml如果来写结果映射
关于 #{} 和 ${}的区别面试考
MyBatis 参数赋值有两种⽅式, 咱们前⾯使⽤了 #{} 进⾏赋值, 接下来我们看下⼆者的区别
5.2.1 #{} 和${} 使⽤
1. 先看Interger类型的参数
发现我们输出的SQL语句:select * from userinfo where id = ?
我们输⼊的参数并没有在后⾯拼接,id的值是使⽤ ? 进⾏占位. 这种SQL 我们称之为"预编译SQL"
JDBC编程使⽤的就是预编译SQL
#{} 改成 ${} 再观察打印的⽇志:
可以看到, 这次的参数是直接拼接在SQL语句中了
2. 接下来我们再看String类型的参数

我们把 #{} 改成 ${} 再观察打印的⽇志:

可以看到, 这次的参数依然是直接拼接在SQL语句中了, 但是字符串作为参数时, 需要添加引号 '' , 使⽤ ${} 不会拼接引号 '' , 导致程序报错
修改代码如下:
从上⾯两个例⼦可以看出:
#{} 使⽤的是预编译SQL, 通过 ? 占位的⽅式, 提前对SQL进⾏编译, 然后把参数填充到SQL语句
中. #{} 会根据参数类型, ⾃动拼接引号 '' .
${} 会直接进⾏字符替换, ⼀起对SQL进⾏编译. 如果参数为字符串, 需要加上引号 '' .
参数为数字类型时, 也可以加上, 查询结果不变, 但是可能会导致索引失效, 性能下降
#{} 和 ${}区别
#{} 和 ${} 的区别就是预编译SQL和即时SQL 的区别.
简单回顾:
当客⼾发送⼀条SQL语句给服务器后, ⼤致流程如下:
1. 解析语法和语义, 校验SQL语句是否正确
2. 优化SQL语句, 制定执⾏计划
3. 执⾏并返回结果
⼀条 SQL如果⾛上述流程处理, 我们称之为 Immediate Statements(即时 SQL)
预编译SQL会对1,2步进行缓存
1. 性能更⾼
绝⼤多数情况下, 某⼀条 SQL 语句可能会被反复调⽤执⾏, 或者每次执⾏的时候只有个别的值不同(⽐如 select 的 where ⼦句值不同, update 的 set ⼦句值不同, insert 的 values 值不同). 如果每次都需要经过上⾯的语法解析, SQL优化、SQL编译等,则效率就明显不⾏了.
预编译SQL,编译⼀次之后会将编译后的SQL语句缓存起来,后⾯再次执⾏这条语句时,不会再次编译(只是输⼊的参数不同), 省去了解析优化等过程, 以此来提⾼效率
2. 更安全(防⽌SQL注⼊)
SQL注⼊:是通过操作输⼊的数据来修改事先定义好的SQL语句,以达到执⾏代码对服务器进⾏攻击的⽅法。
由于没有对⽤⼾输⼊进⾏充分检查,⽽SQL⼜是拼接⽽成,在⽤⼾输⼊参数时,在参数中添加⼀些
SQL关键字,达到改变SQL运⾏结果的⽬的,也可以完成恶意攻击
数据库连接池
在上⾯Mybatis的讲解中, 我们使⽤了数据库连接池技术, 避免频繁的创建连接, 销毁连接
下⾯我们来了解下数据库连接池
介绍
数据库连接池负责分配、管理和释放数据库连接,它允许应⽤程序重复使⽤⼀个现有的数据库连接,
⽽不是再重新建⽴⼀个
没有使⽤数据库连接池的情况: 每次执⾏SQL语句, 要先创建⼀个新的连接对象, 然后执⾏SQL语句, SQL语句执⾏完, 再关闭连接对象释放资源. 这种重复的创建连接, 销毁连接⽐较消耗资源
使⽤数据库连接池的情况: 程序启动时, 会在数据库连接池中创建⼀定数量的Connection对象, 当客⼾请求数据库连接池, 会从数据库连接池中获取Connection对象, 然后执⾏SQL, SQL语句执⾏完, 再把Connection归还给连接池.
优点:
1. 减少了⽹络开销
2. 资源重⽤
3. 提升了系统的性能
使⽤
常⻅的数据库连接池:
C3P0
DBCP
Druid
Hikari
⽬前⽐较流⾏的是 Hikari, Druid
1. Hikari : SpringBoot默认使⽤的数据库连接池
2. Druid
如果我们想把默认的数据库连接池切换为Druid数据库连接池, 只需要引⼊相关依赖即可
< dependency >
< groupId >com.alibaba</ groupId >
< artifactId >druid-spring-boot-3-starter</ artifactId >
< version >1.2.21</ version >
</ dependency >
总结
MySQL 开发企业规范
1. 表名, 字段名使⽤⼩写字⺟或数字, 单词之间以下划线分割. 尽量避免出现数字开头或者两个下划线
中间只出现数字. 数据库字段名的修改代价很⼤, 所以字段名称需要慎重考虑。
MySQL 在 Windows 下不区分⼤⼩写, 但在 Linux 下默认是区分⼤⼩写. 因此, 数据库名, 表名, 字
段名都不允许出现任何⼤写字⺟, 避免节外⽣枝
正例: aliyun_admin, rdc_config, level3_name
反例: AliyunAdmin, rdcConfig, level_3_name
2. 表必备三字段: id, create_time, update_time
id 必为主键, 类型为 bigint unsigned, 单表时⾃增, 步⻓为 1
create_time, update_time 的类型均为 datetime 类型, create_time表⽰创建时间,
update_time表⽰更新时间
有同等含义的字段即可, 字段名不做强制要求
3. 在表查询中, 避免使⽤ * 作为查询的字段列表, 标明需要哪些字段(课堂上给⼤家演⽰除外).
1. 增加查询分析器解析成本
2. 增减字段容易与 resultMap 配置不⼀致
3. ⽆⽤字段增加⽹络消耗, 尤其是 text 类型的字段
#{} 和${} 区别
1. #{}:预编译处理, ${}:字符直接替换
2. #{} 可以防⽌SQL注⼊, ${}存在SQL注⼊的⻛险, 查询语句中, 可以使⽤ #{} ,推荐使⽤ #{}
3. 但是⼀些场景, #{} 不能完成, ⽐如 排序功能, 表名, 字段名作为参数时, 这些情况需要使⽤${}
4. 模糊查询虽然${}可以完成, 但因为存在SQL注⼊的问题,所以通常使⽤mysql内置函数concat来完成
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值