微信咋做自己的网站,百度网站模板免费下载,国外品牌网站建设,电商网站 建设价格目录
#x1f6a9;三层架构
#x1f388;JDBC操作回顾
#x1f6a9;什么是MyBatis
#x1f6a9;MyBatis⼊⻔
#x1f388;准备工作
#x1f4dd;创建⼯程
#x1f4dd;数据准备
#x1f388;配置数据库连接字符串
#x1f388;写持久层代码
#x1f388;单…目录
三层架构
JDBC操作回顾
什么是MyBatis
MyBatis⼊⻔
准备工作
创建⼯程
数据准备
配置数据库连接字符串
写持久层代码
单元测试
MyBatis的基础操作
打印日志
参数传递
增(Insert)
返回主键(实现自增效果)
删(delete)
改(Update)
查(Select)
起别名
结果映射
开启驼峰命名(推荐)
MyBatis XML配置文件
配置连接字符串和MyBatis
写持久层代码
添加 mapper 接⼝
添加 UserInfoXMLMapper2.xml
查询所有⽤⼾的具体实现
单元测试
增删改查操作
增(Insert)
删(Delete)
改(Update)
查(Select) 本节⽬标 1. 使⽤MyBatis完成简单的增删改查操作, 参数传递. 2. 掌握MyBatis的两种写法: 注解 和 XML⽅式 3. 掌握MyBatis 相关的⽇志配置 三层架构 在应⽤分层学习时, 我们 了解到web应⽤程序⼀般分为三层即Controller、Service、Dao . 表现层Controller 参数接收参数校验参数格式转换结果格式转换结果返回等等业务逻辑层Service 介于表现层和数据层之间业务逻辑相关的处理数据层Dao 与数据相关的数据的增删改查 之前的案例中请求流程如下: 浏览器发起请求, 先请求Controller, Controller接收到请求之后, 调⽤ Service进⾏业务逻辑处理, Service再调⽤Dao, 但是Dao层的数据是Mock的, 真实的数据应该从数据库中读取. 我们学习MySQL数据库时已经学习了JDBC来操作数据库, 但是JDBC操作太复杂了. JDBC操作回顾 我们先来回顾⼀下 JDBC 的操作流程: 1. 创建数据库连接池 DataSource 2. 通过 DataSource 获取数据库连接 Connection 3. 编写要执⾏带 ? 占位符的 SQL 语句 4. 通过 Connection 及 SQL 创建操作命令对象 Statement 5. 替换占位符指定要替换的数据库字段类型占位符索引及要替换的值 6. 使⽤ Statement 执⾏ SQL 语句 7. 查询操作返回结果集 ResultSet更新操作返回更新的数量 8. 处理结果集 9. 释放资源 展⽰了通过 JDBC 的 API 向数据库中添加⼀条记录修改⼀条记录查询⼀条记录的操作。 从上述的操作流程中可以看出对于JDBC来说整个操作非常的繁琐不但要拼接每一个参数而且还要按照模板代码的方式一步步的操作数据库并且在每次操作完还要手动关闭连接等而所有的这些操作步骤都需要在每个方法中重复书写那有没有一种方法可以更简单更方便的操作数据库呢 答案是肯定的这就是我们要学习 MyBatis 的真正原因它可以帮助我们更⽅便、更快速的操作数据库. 什么是MyBatis MyBatis是一款优秀的 持久层 框架用于简化JDBC的开发 在上⾯我们提到⼀个词持久层 • 持久层指的就是持久化操作的层, 通常指数据访问层(dao), 是⽤来操作数据库的 简单来说 MyBatis是更简单完成程序和数据库交互的框架也就是更简单的操作和读取数据库工具接下来我们就通过一个入门程序让大家感受一下通过MyBatis如何来操作数据库 MyBatis⼊⻔ Mybatis操作数据库的步骤 1. 准备⼯作(创建springboot⼯程、数据库表准备、实体类) 2. 引⼊Mybatis的相关依赖配置Mybatis(数据库连接信息) 3. 编写SQL语句(注解/XML) 4. 测试 准备工作 创建⼯程 创建springboot⼯程并导⼊ mybatis的起步依赖、mysql的驱动包 Mybatis 是⼀个持久层框架, 具体的数据存储和数据操作还是在MySQL中操作的, 所以需要添加MySQL驱动。 项⽬⼯程创建完成后⾃动在pom.xml⽂件中导⼊Mybatis依赖和MySQL驱动依赖 。 !--Mybatis 依赖包--dependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion3.0.3/version/dependency!--mysql驱动包--
dependencygroupIdcom.mysql/groupIdartifactIdmysql-connector-j/artifactIdscoperuntime/scope
/dependency 数据准备 创建⽤⼾表, 并创建对应的实体类User -- 创建数据库
DROP DATABASE IF EXISTS mybatis_test;
CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;
-- 使⽤数据数据
USE mybatis_test;
-- 创建表[⽤⼾表]
DROP TABLE IF EXISTS userinfo;
CREATE TABLE userinfo (id INT ( 11 ) NOT NULL AUTO_INCREMENT,username VARCHAR ( 127 ) NOT NULL,password VARCHAR ( 127 ) NOT NULL,age TINYINT ( 4 ) NOT NULL,gender TINYINT ( 4 ) DEFAULT 0 COMMENT 1-男 2-⼥ 0-默认,phone VARCHAR ( 15 ) DEFAULT NULL,delete_flag TINYINT ( 4 ) DEFAULT 0 COMMENT 0-正常, 1-删除,create_time DATETIME DEFAULT now(),update_time DATETIME DEFAULT now(),PRIMARY KEY ( id )
) ENGINE INNODB DEFAULT CHARSET utf8mb4;
-- 添加⽤⼾信息
INSERT INTO mybatis_test.userinfo ( username, password, age, gender, phone )
VALUES ( admin, admin, 18, 1, 18612340001 );
INSERT INTO mybatis_test.userinfo ( username, password, age, gender, phone )
VALUES ( zhangsan, zhangsan, 18, 1, 18612340002 );
INSERT INTO mybatis_test.userinfo ( username, password, age, gender, phone )
VALUES ( lisi, lisi, 18, 1, 18612340003 );
INSERT INTO mybatis_test.userinfo ( username, password, age, gender, phone )
VALUES ( wangwu, wangwu, 18, 1, 18612340004 ); 创建对应的实体类 UserInfo 实体类的属性名与表中的字段名⼀⼀对应 package com.example.mybatis_test.model;import lombok.Data;import java.util.Date;Data
public class UserInfo {private Integer id;private String username;private String password;private Integer age;private Integer gender;private String phone;private Integer deleteFlag;private Date createTime;private Date updateTime;
}配置数据库连接字符串 # 数据库连接配置
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncodingutf8useSSLfalseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver 注意事项 如果使⽤ MySQL 是 5.x 之前的使⽤的是com.mysql.jdbc.Driver如果是⼤于 5.x 使⽤的 是“com.mysql.cj.jdbc.Driver”. 写持久层代码 在项⽬中, 创建持久层接⼝UserInfoMapper2. package com.example.mybatis_test.mapper;import com.example.mybatis_test.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;Mapper
public interface UserInfoMapper2 {//查询所有用户的信息Select(select * from userinfo)ListUserInfogetUserInfoAll();
}Mybatis的持久层接⼝规范⼀般都叫 XxxMapper Mapper注解表⽰是MyBatis中的Mapper接⼝ 程序运行时框架会自动生成接口的实现类对象(代理对象并交给Spring的IOC容器管理.也就是在程序运行的时候框架会自动生成UserInfoMapper2接口然后交给了spring的ioc容器中让spring进行管理等需要了就注入Select注解代表的就是select查询也就是注解对应方法的具体实现内容而select就是执行sql语句注解里面的内容就是具体实现内容 单元测试 在创建出来的SpringBoot⼯程中在src下的test⽬录下已经⾃动帮我们创建好了测试类 我们可以直接使⽤这个测试类来进⾏测试. package com.example.mybatis_test.mapper;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class UserInfoMapper2Test {Testvoid getUserInfoAll() {}
} 此时的测试单元类就自动生成了再src/test/java/Mapper里面自动生成了测试类。 package com.example.mybatis_test.mapper;import com.example.mybatis_test.model.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;import static org.junit.jupiter.api.Assertions.*;SpringBootTest
class UserInfoMapper2Test {Autowiredprivate UserInfoMapper2 userInfoMapper2;Testvoid getUserInfoAll() {ListUserInfouserInfosuserInfoMapper2.getUserInfoAll();for (UserInfo userInfo:userInfos) {System.out.println(userInfo);}}
} 记得加 SpringBootTest 注解, 加载Spring运⾏环境否则会报错 测试类上添加了注解 SpringBootTest该测试类在运⾏时就会⾃动加载Spring的运⾏环境. 我们通过Autowired这个注解, 注⼊我们要测试的类, 就可以开始进⾏测试了 。 返回结果中, 可以看到, 只有SQL语句中查询的列对应的属性才有赋值。sql语句和查询的列属性不对应那么就默认为空值。 MyBatis的基础操作 上⾯我们学习了Mybatis的查询操作, 接下来我们学习MyBatis的增, 删, 改操作 在学习这些操作之前, 我们先来学习MyBatis⽇志打印。 打印日志 在Mybatis当中我们可以借助⽇志, 查看到sql语句的执⾏、执⾏传递的参数以及执⾏结果 在配置⽂件中进⾏配置即可。 #配置mybatis日志为了后续观察sql语句的执行
mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ①: 查询语句 preparing:select*from userinfo ②: 传递参数及类型 Parameters③: SQL执⾏结果 cloums以下 我们看到配置日志文件后我们就可以观察到sql语句的执行以及执行结果每一行都标注的清清楚楚并且标注影响的行数。 参数传递 #{}动态参数传递 需求: 查找id4的⽤⼾,对应的SQL就是: select * from userinfo where id4 //查询id4的用户Select(select * from userinfo where id#{id})UserInfo queryById(Integer id); 如果给where id4表示只能查找id4 的数据, 所以SQL语句中的id值不能写成固定数值需要变为动态的数值 解决⽅案在queryById⽅法中添加⼀个参数(id) 将⽅法中的参数传给SQL语句 使⽤ #{} 的⽅式获取⽅法中的参数使静态数据转成动态数据 如果mapper接⼝⽅法形参只有⼀个普通类型的参数#{…} ⾥⾯的属性名可以随便写如#{id}、# {value}。 建议和参数名保持⼀致 添加测试样例 Testvoid queryById() {UserInfo userInfouserInfoMapper2.queryById(4);System.out.println(userInfo);} 控制台结果 也可以通过 Param , 设置参数的别名 , 如果使⽤ Param 设置别名, #{...}⾥⾯的属性名必须和 Param 设置的⼀样 增(Insert) //增加一个用户Insert(insert into userinfo (username,password,age,gender) values (#{username},#{password},#{age},#{gender}))Integer insert(UserInfo userInfo); 如果语句过长我们可以直接敲回车idea会自动给你换行。 添加测试样例 Testvoid insert() {UserInfo userInfonew UserInfo();userInfo.setUsername(zyf);userInfo.setPassword(1005);userInfo.setAge(20);userInfo.setGender(1);Integer countuserInfoMapper2.insert(userInfo);System.out.println(count);} 控制台结果 如果设置了 Param 属性, #{...} 需要使⽤ 参数.属性 来获取 //增加一个用户Insert(insert into userinfo (username,password,age,gender) values (#{userinfo.username},#{userinfo.password},#{userinfo.age},#{userinfo.gender}))Integer insert(Param(userinfo) UserInfo userInfo); 返回主键(实现自增效果) 自增id Options(useGeneratedKeys true, keyProperty id) useGeneratedKeys这会令 MyBatis 使⽤ JDBC 的 getGeneratedKeys ⽅法来取出由数据库内 部⽣成的主键⽐如像 MySQL 和 SQL Server 这样的关系型数据库管理系统的⾃动递增字 段默认值false. • keyProperty指定能够唯⼀识别对象的属性MyBatis 会使⽤ getGeneratedKeys 的返回值或insert 语句的 selectKey ⼦元素设置它的值默认值未设置unset Insert 语句默认返回的是 受影响的⾏数 但有些情况下, 数据插⼊之后, 还需要有后续的关联操作, 需要获取到新插⼊数据的id ⽐如订单系统 当我们下完订单之后, 需要通知物流系统, 库存系统, 结算系统等, 这时候就需要拿到订单ID 如果想要拿到⾃增id, 需要在Mapper接⼝的⽅法上添加⼀个Options的注解 注意: 设置 useGeneratedKeystrue 之后, ⽅法返回值依然是受影响的⾏数, ⾃增id 会设置在上 述 keyProperty 指定的属性中. 删(delete) 使用注解 Delete(delete from userinfo where id#{id})Integer delete(Integer id); 添加测试样例 此时的表中就删除了id4的用户。 改(Update) 使用注解 //更新一个用户的姓名Update(update userinfo set username#{username} where id#{id})Integer update(String username,Integer id); 添加测试样例 Testvoid update() {Integer countuserInfoMapper2.update(zyf,5);System.out.println(count);} 查(Select) 我们在上⾯查询时发现, 有⼏个字段是没有赋值的, 只有Java对象属性和数据库字段⼀模⼀样时, 才会进⾏赋值 接下来我们多查询⼀些数据 使用注解 Select(select id, username, password, age, gender, phone, delete_flag, create_time, update_time from userinfo)ListUserInfo queryAllUser(); 添加测试样例 Testvoid queryAllUser() {ListUserInfoinfoListuserInfoMapper2.queryAllUser();for (UserInfo userInfo:infoList) {System.out.println(userInfo);}} 从运⾏结果上可以看到, 我们SQL语句中, 查询了delete_flag, create_time, update_time, 但是这⼏个属性却没有赋值. 原因分析: 当⾃动映射查询结果时 MyBatis 会获取结果中返回的列名并在 Java 类中查找相同名字的属性忽略⼤⼩写 。 这意味着如果发现了 ID 列和 id 属性MyBatis 会将列 ID 的值赋给 id 属性 但是有三个属性和表的列名不一致就不会进行赋值。 解决办法: 1. 起别名 2. 结果映射 3. 开启驼峰命名 MyBatis 会根据⽅法的返回结果进⾏赋值. ⽅法⽤对象 UserInfo接收返回结果, MySQL 查询出来数据为⼀条, 就会⾃动赋值给对象. ⽅法⽤ListUserInfo接收返回结果, MySQL 查询出来数据为⼀条或多条时, 也会⾃动赋值给List. 但如果MySQL 查询返回多条, 但是⽅法使⽤UserInfo接收, MyBatis执⾏就会报错 起别名 在SQL语句中 给列名起别名保持别名和实体类属性名⼀样。 delete_flag as deleteFlag, create_time as createTime, update_time as updateTime 使用注解 Select(select id, username, password, age, gender, phone, delete_flag as deleteFlag, create_time as createTime, update_time as updateTime from userinfo)ListUserInfo queryAllUser2(); SQL语句太⻓时, 使⽤加号 进⾏字符串拼接直接按回车idea自动给你换行 添加测试 Testvoid queryAllUser2() {ListUserInfoinfoListuserInfoMapper2.queryAllUser2();for (UserInfo userInfo:infoList) {System.out.println(userInfo);}} 结果映射 Select(select id, username, password, age, gender, phone, delete_flag, create_time, update_time from userinfo)Results({Result(column delete_flag,property deleteFlag),Result(column create_time,property createTime),Result(column update_time,property updateTime)})ListUserInfo queryAllUser(); 如果其他SQL, 也希望可以复⽤这个映射关系, 可以给这个Results定义⼀个名这样我们再queryById方法中我们要想得到id4的用户他查询之后的结果也是那三个属性不对应我们就可以复用下面的Results注解用RestultMap注解定位到Results注解中id。 使⽤ id 属性给该 Results 定义别名, 使⽤ ResultMap 注解来复⽤其他定义的 ResultMap 测试结果 开启驼峰命名(推荐) 通常数据库列使⽤蛇形命名法进⾏命名(下划线分割各个单词), Java 属性⼀般遵循驼峰命名法约定. 驼峰命名规则 abc_xyz abcXyz • 表中字段名abc_xyz • 类中属性名abcXyz 为了在这两种命名⽅式之间启⽤⾃动映射需要将 mapUnderscoreToCamelCase 设置为 true。 mybatis:configuration:map-underscore-to-camel-case: true #配置驼峰⾃动转换 配置驼峰自动转换 //查询所有用户的信息Select(select * from userinfo)ListUserInfogetUserInfoAll(); 添加测试样例 Testvoid getUserInfoAll() {ListUserInfouserInfosuserInfoMapper2.getUserInfoAll();for (UserInfo userInfo:userInfos) {System.out.println(userInfo);}} 相比于起别名和结果映射开启驼峰命名更加的简单只需要再配置文件中配置一下即可。 MyBatis XML配置文件 上⾯学习了注解的⽅式, 接下来我们学习XML的⽅式 使⽤Mybatis的注解⽅式主要是来完成⼀些简单的增删改查功能. 如果需要实现复杂的SQL功能建议使⽤XML来配置映射语句也就是将SQL语句写在XML配置⽂件中. MyBatis XML的⽅式需要以下两步: 1. 配置数据库连接字符串和MyBatis 2. 写持久层代码 配置连接字符串和MyBatis 此步骤需要进⾏两项设置数据库连接字符串设置和 MyBatis 的 XML ⽂件配置。 如果是application.yml⽂件, 配置内容如下: # 配置 mybatis xml 的⽂件路径在 resources/mapper 创建所有表的 xml ⽂件
mybatis:mapper-locations: classpath:mapper/**Mapper.xml spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncodingutf8useSSLfalseusername: rootpassword: 105528clzyf.driver-class-name: com.mysql.cj.jdbc.Driver
#配置mybatis日志为了后续观察sql语句的执行
mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
##配置驼峰⾃动转换map-underscore-to-camel-case: true
# 配置 mybatis xml 的⽂件路径在 resources/mapper 创建所有表的 xml ⽂件mapper-locations: classpath:mapper/UserInfoMapper2.xml 配置mybatis.xml文件我们需要在src/main/resources/mapper目录下创建xml文件。 写持久层代码 持久层代码分两部分 1. ⽅法定义 Interface 2. ⽅法实现: UserInfoMapper2.xml Interface用于方法定义xxx.xml用于方法的实现实现sql语句。 添加 mapper 接⼝ 数据持久层的接⼝定义 package com.example.mybatis_test.mapper;import com.example.mybatis_test.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;import java.util.List;Mapper
public interface UserInfoXmlMapper2 {ListUserInfoqueryAllUser();
} 添加 UserInfoXMLMapper2.xml 数据持久成的实现MyBatis 的固定 xml 格式 ?xml version1.0 encodingUTF-8?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.example.mybatis_test.mapper.UserInfoXmlMapper2/mapper 创建UserInfoXMLMapper2.xml, 路径参考yml中的配置 # 配置 mybatis xml 的⽂件路径在 resources/mapper 创建所有表的 xml ⽂件mapper-locations: classpath:mapper/UserInfoMapper2.xml 查询所有⽤⼾的具体实现 ?xml version1.0 encodingUTF-8?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.example.mybatis_test.mapper.UserInfoXmlMapper2select idqueryAllUserselect username,password,age,gender,phone, from userinfo/select
/mapper 以下是对以上标签的说明 • mapper 标签需要指定 namespace 属性表⽰命名空间值为 mapper 接⼝的全限定名包括全包名.类名。 • select 查询标签是⽤来执⾏数据库的查询操作的 ◦ id 是和 Interface 接⼝中定义的⽅法名称⼀样的 表⽰对接⼝的具体实现⽅法。 ◦ resultType 是返回的数据类型也就是开头我们定义的实体类. 单元测试 SpringBootTest
class UserInfoMapper2Test {Autowiredprivate UserInfoMapper2 userInfoMapper2;Testvoid getUserInfoAll() {ListUserInfouserInfosuserInfoMapper2.getUserInfoAll();for (UserInfo userInfo:userInfos) {System.out.println(userInfo);}}
} 增删改查操作 增(Insert) UserInfoMapper2接⼝: ///增Integer insertUser(UserInfo userInfo); UserInfoMapper.xml实现 insert idinsertUserinsert into userinfo (username,password,age,gender,phone)values (#{username},#{password},#{age},#{gender},#{phone})/insert 如果使⽤Param设置参数名称的话, 使⽤⽅法和注解类似 UserInfoMapper接⼝: ///增Integer insertUser(Param(userinfo) UserInfo userInfo); UserInfoMapper.xml实现: insert idinsertUserinsert into userinfo (username,password,age,gender,phone)values (#{userinfo.username},#{userinfo.password},#{userinfo.age},#{userinfo.gender},#{userinfo.phone})/insert 返回⾃增 id 接⼝定义不变, Mapper.xml 实现 设置useGeneratedKeys 和keyProperty属性 insert idinsertUser useGeneratedKeystrue keyPropertyidinsert into userinfo (username,password,age,gender,phone)values (#{userinfo.username},#{userinfo.password},#{userinfo.age},#{userinfo.gender},#{userinfo.phone})/insert 删(Delete) UserInfoMapper接⼝ //删Integer deleteUser(Integer id); UserInfoMapper.xml实现: delete iddeleteUserdelete from userinfo where id#{id};/delete 测试 Testvoid deleteUser() {Integer countuserInfoXmlMapper2.deleteUser(2);System.out.println(count);} 改(Update) UserInfoMapper接⼝ //改Integer updateUser(String username,Integer id); UserInfoMapper.xml实现: update idupdateUserupdate userinfo set username#{username} where id#{id}/update 测试 Testvoid updateUser() {Integer countuserInfoXmlMapper2.updateUser(zzzzz,7);System.out.println(count);} 查(Select) 同样的, 使⽤XML 的⽅式进⾏查询, 也存在数据封装的问题 我们把SQL语句进⾏简单修改, 查询更多的字段内容 UserInfoMapper接⼝ //查ListUserInfoselectUser(); UserInfoMapper.xml实现: select idselectUserselect id, username,password, age, gender, phone, delete_flag,create_time, update_time from userinfo/select 测试 Testvoid selectUser() {ListUserInfoinfoListuserInfoXmlMapper2.selectUser();for (UserInfo userInfo:infoList) {System.out.println(userInfo);}} 结果显⽰: deleteFlag, createTime, updateTime 也没有进⾏赋值. 解决办法和注解类似 1. 起别名 2. 结果映射 3. 开启驼峰命名 其中1,3的解决办法和注解⼀样,不再多说, 接下来看下xml如果来写结果映射 结果映射 resultMap idBaseMap typecom.example.mybatis_test.model.UserInfoid columnid propertyid/idresult columndelete_flag propertydeleteFlag/resultresult columncreate_time propertycreateTime/resultresult columnupdate_time propertyupdateTime/result/resultMapselect idselectUser resultMapBaseMapselect id, username,password, age, gender, phone, delete_flag,create_time, update_time from userinfo/select 注解方式和XML方式结果映射区别 六一快乐~今天吃了自助餐几年没有穿裙子今天买了个裙子给张老师买了白色上袖为it文化节准备上台。