本篇博客讲记录:
1.回顾MySQL的JDBC操作
2..Mybatis简介、Mybatis操作数据库的步骤
3.Mybatis 相关日志的配置(日志的配置、驼峰自动转换的配置)
前言
之前学习应用分层时我们知道Web应用程序一般分为三层,Controller、Service、Dao。
浏览器发起请求、现请求Controller、Controller接收到请求后,调用Service进行业务逻辑处理。Service再调用Dao。Dao再从数据库中获取数据。今天我们就来讲解Mybatis数据库。
学习MySQL数据库时,已经学习了JDBC来操作数据库。而JDBC操作很复杂。这就是我们要学习 MyBatis 的真正原因,它可以帮助我们更方便、更快速的操作数据库。Mybatis就是对JDBC封装后的结果。
一、JDBC操作示例回顾:
JDBC操作步骤
1. 创建数据库连接池DataSource
private final DataSource dataSource; public SimpleJdbcOperation(DataSource dataSource) { this.dataSource = dataSource; }
2. 通过DataSource获取数据库连接Connection
public void addBook() { Connection connection = null; PreparedStatement stmt = null; try { //获取数据库连接 connection = dataSource.getConnection();
3. 编写要执行带?占位符的SQL语句(预编译SQL)(不能封装)
//创建语句 stmt = connection.prepareStatement( "insert into soft_bookrack (book_name, book_author, book_isbn) values (?,?,?);" );
4. 通过Connection及SQL创建操作命令对象Statement
PreparedStatement stmt = null;
5. 替换占位符:指定要替换的数据库字段类型,占位符索引及要替换的值(不能封装)
//参数绑定 stmt.setString(1, "Spring in Action"); stmt.setString(2, "Craig Walls"); stmt.setString(3, "9787115417305");
6. 使用Statement执行SQL语句
//执⾏语句 stmt.execute();
7. 查询操作:返回结果集ResultSet,更新操作:返回更新的数量
//执⾏语句 rs = stmt.executeQuery(); if (rs.next()) { book = new Book(); book.setName(rs.getString("book_name")); book.setAuthor(rs.getString("book_author")); book.setIsbn(rs.getString("book_isbn")); } System.out.println(book);
8. 处理结果集
} catch (SQLException e) { //处理异常信息
9. 释放资源
} finally { //清理资源 try { if (stmt != null) { stmt.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { // } }
由于使用JDBC时,太多内容重复操作,并且步骤繁琐。为了更加方便我们操作数据库。我们对这些非个性化的步骤进行封装。因此Mybatis就诞生了。
①如果Mybatis字段和Java属性一样,Mybatis会自动进行赋值,对于不一样的字段,需要我们告诉Mybatis,字段和属性的映射关系。
最终我们发现只有第三条和第五条是需要我们手动操作的。其他的一切都有规律可循。因此我们将其他步骤进行封装,只留一个接口让你去填SQL语句和赋值的参数。其他Mybatis都帮你搞定。
-- 创建数据库
create database if not exists library default character set utf8mb4;
-- 使⽤数据库
use library;
-- 创建表
create table if not exists soft_bookrack (
book_name varchar(32) NOT NULL,
book_author varchar(32) NOT NULL,
book_isbn varchar(32) NOT NULL primary key
);
以下是 JDBC 操作的具体实现代码:
package com.example.demo.mapper;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class SimpleJdbcOperation {
private final DataSource dataSource;
public SimpleJdbcOperation(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 添加⼀本书
*/
public void addBook() {
Connection connection = null;
PreparedStatement stmt = null;
try {
//获取数据库连接
connection = dataSource.getConnection();
//创建语句
stmt = connection.prepareStatement(
"insert into soft_bookrack (book_name, book_author,
book_isbn) values (?,?,?);"
);
//参数绑定
stmt.setString(1, "Spring in Action");
stmt.setString(2, "Craig Walls");
stmt.setString(3, "9787115417305");
//执⾏语句
stmt.execute();
} catch (SQLException e) {
//处理异常信息
} finally {
//清理资源
try {
if (stmt != null) {
stmt.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
//
}
}
}
/**
* 更新⼀本书
*/
public void updateBook() {
Connection connection = null;
PreparedStatement stmt = null;
try {
//获取数据库连接
connection = dataSource.getConnection();
//创建语句
stmt = connection.prepareStatement(
"update soft_bookrack set book_author=? where book_isbn=?;"
);
//参数绑定
stmt.setString(1, "张卫滨");
stmt.setString(2, "9787115417305");
//执⾏语句
stmt.execute();
} catch (SQLException e) {
//处理异常信息
} finally {
//清理资源
try {
if (stmt != null) {
stmt.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
//
}
}
}
/**
* 查询⼀本书
*/
public void queryBook() {
Connection connection = null;
PreparedStatement stmt = null;
ResultSet rs = null;
Book book = null;
try {
//获取数据库连接
connection = dataSource.getConnection();
//创建语句
stmt = connection.prepareStatement(
"select book_name, book_author, book_isbn from
soft_bookrack where book_isbn =?"
);
//参数绑定
stmt.setString(1, "9787115417305");
//执⾏语句
rs = stmt.executeQuery();
if (rs.next()) {
book = new Book();
book.setName(rs.getString("book_name"));
book.setAuthor(rs.getString("book_author"));
book.setIsbn(rs.getString("book_isbn"));
}
System.out.println(book);
} catch (SQLException e) {
//处理异常信息
} finally {
//清理资源
try {
if (rs != null) {
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
//
}
}
}
public static class Book {
private String name;
private String author;
private String isbn;
//省略 setter getter ⽅法
}
}
二、什么是Mybatis?
MyBatis是一款优秀的持久层框架,用于简化JDBC的开发。
MyBatis本是Apache的⼀个开源项目iBatis,2010年这个项目由apache迁移到了googlecode,并 且改名为MyBatis。2013年11月迁移到Github。
Mybatis官网:https://blog.mybatis.org
Mybatis中文网:MyBatis中文网
持久层:指的就是持久化操作的层,通常指数据访问层(dao),是用来操作数据库(DB)的.
简单来说MyBatis是更简单完成程序和数据库交互的框架,也就是更简单的操作和读取数据库工具 接下来,我们就通过⼀个入门程序,让大家感受下一通过Mybatis如何来操作数据库
Mybatis操作数据库的步骤:
1.准备工作:创建Springboot工程、数据库表准备、实体类
2.引入Mybatis相关依赖(Mybatis Framework、Mysql Drive)、配置Mybatis数据库连接信息。
3.编写SQL语句(注解/XML)
4.测试
配置Mybatis。
我们使用配置文件application.yml类型的文件进行配置。配置代码如下
驼峰自动转换就可以让我们在数据库中存在的映射关系进行匹配成功
例如字段
delete_flag → deleteFlag
create_time →createTime
updata_time →updataTime
此时数据库的字段名称就可以与我们在实体类创建的成员属性相匹配,这样打印出来的有分割的类似这种数据库表字段updata_time 就可以被识别打印了 而不是打印的null。
三、Mybatis在IDEA中的操作方法:
3.1 第一步:准备工作(创建springboot工程、数据库表准备、实体类)
3.1.1创建springboot工程
首先创建SpringBoot项目。选择Maven来管理项目。选择Mybatis Framework,MySQL Driver等依赖。在项目左侧的数据库栏添加配置数据库。并新建表,创建已经准备好的数据库表。
Mybatis是一个持久层框架,具体的数据存储和数据操作还是在MySQL中操作的,所以需要添加 MySQL驱动
3.1.2数据库表准备
如我们现在要创建一个用户表,并要创建对应的实体类
建表规范
常见规范:
1.字段全部小写,单词之间使用_分割(数据库的字段修改代价非常大,数据量很大!)
2.建表需要具备三个字段,哪怕你不用 (id create_time updata_time)
使互联网上有迹可循
delete_flag删除标志(1.逻辑删除(企业)(通过更新),2.物理删除(delete))
create_time updata_time 这两个字段使用Data类型是因为这个类型保存的时间是非常细节的,可以细致到时分秒。
--创建数据库 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' );
3.1.3对应的实体类
配置好数据库之后,在Idea中创建一个实体类。对应数据库表中的元素
对应的实体类
实体类的属性名与表中的字段名⼀⼀对应
注意Data类型是java.util包下面的,代表的是时间日期。
3.2 第二步:引入Mybatis的相关依赖
引入Mybatis的相关依赖
引入的依赖就是上面我们选择的Mybatis Framework,MySQL Driver等依赖。在pom.xml文件中,我们会看到我们引入的依赖信息;
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency>
若我们在选择依赖的时候忘了选择,我们可以在pom.xml文件中右键,点击第一个选项,我们之前下载好的插件。从这里我们可以继续选择依赖。
3.1.3 配置数据库连接字符串
①使用配置文件
配置文件代码如下
# 数据库连接配置
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
说明
- url: 数据库的 JDBC 连接 URL。请确保 IP 地址、端口号、数据库名称以及连接参数正确。
- username: 数据库用户名称(默认为root)。
- password: 数据库用户密码(这个是安装MySQL的时候设置的密码)。
- driver-class-name: 使用的 JDBC 驱动类,这里指定
com.mysql.cj.jdbc.Driver
是 MySQL 8.x 使用的驱动类url: jdbc:mysql://127.0.0.1:3306/mybatis_test? characterEncoding=utf8&useSSL=false
这个url中
jdbc: 表示Java Database Connectivity (JDBC)API进行数据库链接。
mysql:指定要连接的数据库类型为mysql
127.0.0.1:3306:这是数据库服务器的IP地址和端口号
mybatis_test:数据库名称(要确保这个数据库已经在MySQL服务器上面创建)
?:?后面这是;连接参数部分,以?开始,多个参数用&分隔。
characterEncoding=utf8&useSSL=false:设置字符编码为
UTF-8、
指定不使用 SSL 加密连接。
注:
配置好了之后就可以直接访问数据库了。不过为了更直观的看到数据库中的信息。我们通常不会通过MySQL来操作。
1.我们可以使用数据库管理工具Navicat Premium来管理我们的数据库。
2.我们也可以不用配置文件。直接在IDEA中自带的数据库中直接添加数据源。
②不使用配置文件
直接在IDEA中自带的数据库中直接添加数据源。选择MySQl。
输入名称、用户名、密码、数据库名称点击确定。这样数据库就被导入进来了。
我们可以右键这个数据库来创建表。复制我们之前准备好的数据。粘贴进去点击确定。表就被创建好了
3.3 第三步:编写SQL语句(注解/XML)
为了避免标题级别过多,文章内容过多。我们将这一步放在下一篇文章来详细说明。
3.4 第四步:测试
测试实际上很简单,只需要在我们添加了注解的SQL语句右侧右键,点击生成。再点击测试即可。
我们点击测试, 我们就会进入UserInfoMapperTest这个类。
/**
* 是开发人员的自测代码
*/
//上面的三角运行是执行所有的Test方法
@Slf4j
@SpringBootTest //帮助我们加载Spring的运行环境
class UserInfoMapperTest {
@Autowired//
private UserInfoMapper userInfoMapper;//注入Mapper
@BeforeEach
void setUp() {//表示Test方法执行前执行
log.info("setUp...");
} //执行Test方法前执行
@AfterEach
void tearDown() {//表示Test方法执行后执行
log.info("tearDown...");
} //执行Test方法后执行
// 下面的三角运行符号表示执行当前Test方法
@Test
void queryUserList() {
log.info(userInfoMapper.queryUserList().toString());
}
}
报错
这是SQL语句出错、检查SQL语句就好了。
四、Mybatis相关配置文件
4.1配置Mybatis打印日志
mybatis: configuration: # 配置打印 MyBatis⽇志 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
配置后Mybatis日志。多了如下内容,更加方便我们查看数据库。这是MySQL
返回的结果。
![]()
对通过注解+SQL语句查的补充:驼峰转换
虽然我们编写了如下关于查的相关SQL语句,在MySQL放回的结果中我们可以看到delete_flage,create_time,update_time的值,但是通过Mybatis查询的结果并没有这些值,这是为什么呢?因为MySQL中的字段名是delete_flage,create_time,update_time带有分隔符,而在实体类中我们写的是deleteFlag,createTime,updateTime是不一样的。因此Mybatis并没有访问到MySQL中的相对应字段值。如何解决这个问题呢?有三种办法。
三种办法解决deleteFlag,createTime,updateTime为null
1.改别名
2.通过注解来映射
(也可以复用通过@ResultMap注解,@ResultMap(value = “BaseResult”))
4.2 第三种:配置自动驼峰的转换
将下文添加到配置文件application.yml中,代码不做任何处理
mybatis: configuration: map-underscore-to-camel-case: true # 配置驼峰自动转换