Mybatis入门
一、介绍
- 我们之前学习数据库设计、操作、优化,都是基于图形化工具IDEA,或者DataGrip当中来操作的,通过图形界面或者直接在查询控制台中编写SQL语句来完成数据的增删改查操作。
- 以后在项目开发当中,并不会每次都基于图形化界面工具来操作数据库中的数据,而是要通过Java程序来完成数据库的操作
- 而Java程序来操作数据库,目前最主流的技术当属 Mybatis
-
MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。
- JDBC:JavaEE的十三项规范之一,是sun公司提供的,用来操作数据库的一套规范(直接使用底层的JDBC程序来操作数据库会非常的繁琐,所以现在使用的都是Mybatis框架来简化JDBC的开发)
- MyBatis本是 Apache的一个开源项目iBatis, 2010年这个项目由apache迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
- 官网:Mybatis
二、入门程序
1. 需求
-
使用 Mybatis 查询所有用户数据。
-
直接使用图形化工具查询:
- 就一句sql语句的事情,不过需求是要使用 Mybatis 来。
-
2. 步骤
(1) 准备工作
-
准备工作:创建数据库与表user、创建springboot工程
-
创建数据库与表user
-- 创建数据库并使用 create database mybatis; use mybatis; -- 创建user用户表 create table user ( id int unsigned primary key auto_increment comment 'ID', name varchar(100) comment '姓名', age tinyint unsigned comment '年龄', gender tinyint unsigned comment '性别, 1:男, 2:女', phone varchar(11) comment '手机号' ) comment '用户表'; -- 插入用户数据 insert into user(id, name, age, gender, phone) VALUES (null, '白眉鹰王', 55, '1', '18800000000'); insert into user(id, name, age, gender, phone) VALUES (null, '金毛狮王', 45, '1', '18800000001'); insert into user(id, name, age, gender, phone) VALUES (null, '青翼蝠王', 38, '1', '18800000002'); insert into user(id, name, age, gender, phone) VALUES (null, '紫衫龙王', 42, '2', '18800000003'); insert into user(id, name, age, gender, phone) VALUES (null, '光明左使', 37, '1', '18800000004'); insert into user(id, name, age, gender, phone) VALUES (null, '光明右使', 48, '1', '18800000005');
-
创建springboot工程
-
实体类User:
- 创建实体类User,属性必须对应user表的字段
package com.app.pojo; public class User { private Integer id; private String name; private Short age; private Short gender; private String phone; public User() { } public User(Integer id, String name, Short age, Short gender, String phone) { this.id = id; this.name = name; this.age = age; this.gender = gender; this.phone = phone; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Short getAge() { return age; } public void setAge(Short age) { this.age = age; } public Short getGender() { return gender; } public void setGender(Short gender) { this.gender = gender; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", gender=" + gender + ", phone='" + phone + '\'' + '}'; } }
-
(2) 引入-配置Mybatis
-
引入Mybatis的相关依赖,配置Mybatis(数据库连接信息)
-
注意:我使用maven-3.9.4,依赖无法自动联网下载,使用3.6.1就可以。
-
pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- 所有springboot工程都是继承这个父工程 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.15</version> <relativePath/> <!-- lookup parent from repository --> </parent> <!-- 工程坐标信息 --> <groupId>com.app</groupId> <artifactId>springboot-mybatis-quickstart</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot-mybatis-quickstart</name> <description>Demo project for Spring Boot</description> <!-- jdk版本号 --> <properties> <java.version>11</java.version> </properties> <dependencies> <!-- mybatis起步依赖 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.3.1</version> </dependency> <!-- 最新版本的mysql数据库驱动包依赖 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <!-- 上个版本的mysql数据库驱动包依赖 --> <!-- <dependency>--> <!-- <groupId>mysql</groupId>--> <!-- <artifactId>mysql-connector-java</artifactId>--> <!-- <scope>runtime</scope>--> <!-- </dependency>--> <!-- springboot单元测试依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter-test</artifactId> <version>2.3.1</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
-
application.properties:
- 数据库版本
- 数据库连接的url、用户名、密码改成自己的即可!
# 配置数据库连接信息: #驱动类名称 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #数据库连接的url spring.datasource.url=jdbc:mysql://localhost:3306/mybatis #连接数据库的用户名 spring.datasource.username=root #连接数据库的密码 spring.datasource.password=12345
-
(3) 编写SQL语句
- 编写SQL语句(注解/XML)
package com.app.mapper;
import com.app.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper //作用:运行时,会自动生成该接口的实现类对象(代理对象),会将该对象交给IOC容器管理
public interface UserMapper {
//查询所有用户信息
@Select("select * from user")
public List<User> list();
}
(4) 单元测试
package com.app;
import com.app.mapper.UserMapper;
import com.app.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest //Springboot整合单元测试的注解
class SpringbootMybatisQuickstartApplicationTests {
@Autowired //依赖注入
private UserMapper userMapper;
@Test
public void testListUser(){
//调用userMapper中的list()方法,来查询所有用户信息
List<User> list = userMapper.list();
//基于stream流的方式遍历输出
list.stream().forEach(user -> System.out.println(user));
}
}
3. 总结
- @Mapper:
- 作用:运行时,会自动生成该接口的实现类对象(代理对象),会将该对象交给IOC容器管理。
- @Select:
- 作用:执行 SQL 查询语句,并把查询结果映射到指定的 Java 对象中。
- @SpringBootTest:
- 作用:springboot整合单元测试的注解
- @Autowired:
- 作用:会在IOC容器中自动寻找同类型参数为其传值
三、配置SQL提示
1. 问题一
-
默认在mybatis中编写SQL语句是不识别的。
-
目前在注解 @Select 的 value 中写sql语句,即使写错了,脱离了sql语法,也不会提示语法错误。
-
如果等运行时才报错,这样就会大大提高程序出错概率,大大降低开发效率。
2. 配置提示
3. 问题二
- 为啥 user 是爆红?因为没有连接数据库,所以IDEA无法识别
- 产生原因:IDEA和数据库没有建立连接,不识别表信息
4. 连接数据库
四、JDBC
1. 介绍
- JDBC: ( Java DataBase Connectivity ),就是使用Java语言操作关系型数据库的一套API。
-
sun公司官方定义的一套操作所有关系型数据库的规范,即接口。
-
各个数据库厂商去实现这套接口,提供数据库 驱动jar包。
-
我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
2. JDBC实现
package com.app;
import com.app.mapper.UserMapper;
import com.app.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
@SpringBootTest //springboot整合单元测试的注解
class SpringbootMybatisQuickstartApplicationTests {
@Autowired //依赖注入
private UserMapper userMapper;
//Mybatis
@Test
public void testListUser(){
//调用userMapper中的list()方法,来查询所有用户信息
List<User> list = userMapper.list();
//基于stream流的方式遍历输出
list.stream().forEach(user -> System.out.println(user));
}
//JDBC
@Test
public void testJDBC() throws Exception{
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取连接对象
String url = "jdbc:mysql://localhost:3306/mybatis";
String username = "root";
String password = "12345";
Connection connection = DriverManager.getConnection(url, username, password);
//3.获取执行SQL的对象Statement,执行SQL,返回结果
String sql = "select * from user";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
//4.解析并封装结果数据
List<User> userList = new ArrayList<>();
//解析
while (resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
short age = resultSet.getShort("age");
short gender = resultSet.getShort("gender");
String phone = resultSet.getString("phone");
//封装
User user = new User(id, name, age, gender, phone);
userList.add(user);
}
//5.释放资源
statement.cancel();
connection.close();
//6.遍历输出
userList.stream().forEach(user -> System.out.println(user));
}
}
3. 问题
(1) 硬编码
-
这部分的代码经常需要变动:
- 开发阶段需要连接开发数据库、测试阶段需要连接测试数据库、生产阶段需要连接生产数据库
- 则 url、username、password 需要经常变动。
- 如下JDBC是写死在Java代码中的,这就叫硬编码。
-
弊端:
- 一旦这块内容发生变化,代码需要重新编译、打包之后才能运行
(2) 繁琐
-
这部分解析结果的代码:
- 需要一个字段一个字段的解析,还需要考虑这个字段是什么类型的,需要考虑调用什么样的方法
- 字段少倒没问题,如果表结构字段很多,这部分代码将变得无比繁琐、臃肿
(3) 资源浪费&性能降低
-
这部分获取连接、释放资源的代码:
- 在执行sql语句之前,需要先获取连接
- sql语句执行之后,需要释放资源,则马上把这个连接关闭了
- 如果在项目中这么去做的话,频繁的去获取连接、释放连接,会造成资源的浪费、系统性能降低
4. Mybatis VS JDBC
(1) 解决硬编码
- Mybatis中,是将数据库连接的四要素直接配置在了:application.properties 文件中
- 如果要改动,就不需要修改Java代码了,直接修改配置文件即可。
(2) 解决繁琐
- Mybatis中,自动化:将查询返回的每一条记录封装为一个User对象,所有User对象会封装进List集合中
(3) 解决资源浪费&性能降低
-
Mybatis中,在 application.properties 中配置数据库连接信息的时候,所有的配置项前缀都是:spring.datasource.
-
当按照这种方式来配置数据库连接信息之后,SpringBoot底层会自动的采用:数据库连接池技术(统一管理、分配连接)
-
连接:Connection对象
-
有了连接池之后,每一次在执行sql语句时,只需要从连接池中获取一个连接,然后来执行指定的sql语句:
-
当sql语句执行完毕之后,再将这个连接归还给连接池,这样可以做到连接的复用,从而避免了频繁的获取连接、释放连接而造成的资源浪费、性能降低
5. 总结
五、数据库连接池
1. 概述
-
数据库连接池是个容器,负责分配、管理数据库连接(Connection)。
-
它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。
-
释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏。
2. 优势
-
资源重用
-
提升系统响应速度
-
避免数据库连接遗漏
-
JDBC是连接数据库时创建一个连接,执行完SQL语句之后,连接就扔掉了。
-
Mybatis中,是连接数据库时从数据库连接池中拿一个连接,执行完SQL语句之后,就会还回数据库连接池中。
3. 切换数据库连接池
(1) 介绍
-
标准接口:DataSource
-
官方(sun)提供的数据库连接池接口,由第三方组织实现此接口。
-
功能:获取连接
Connection getConnection() throws SQLException;
-
-
常见产品:
-
Druid(德鲁伊)
- Druid连接池是阿里巴巴开源的数据库连接池项目
- 功能强大,性能优秀,是Java语言最好的数据库连接池之一
-
切换Druid数据库连接池
- 官方地址:Druid
-
默认是Hikari:
(2) 方式1
-
依赖:
<!-- Druid(德鲁伊) --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.8</version> </dependency>
(3) 方式2
-
在方式1的基础上,通过配置 application.properties 文件来切换:
# 配置数据库连接信息 - 四要素 #驱动 spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver #数据库连接url spring.datasource.druid.url=jdbc:mysql://localhost:3306/mybatis #用户名 spring.datasource.druid.username=root #密码 spring.datasource.druid.password=12345
4. 总结
(1)数据库连接池
- 是一个容器,负责分配、管理数据库连接(Connection)
- 优势:资源复用、提升系统响应速度
- 接口:DataSource
- 产品:C3P0、DBCP、Druid、Hikari
六、lombok工具包
1. 问题分析
- 我们之前在编写实体类的时候,虽然可以通过快捷方式生成:Getter、Setter、toString()、无参构造、有参构造…
- 但是,实体类多的时候还是显得很繁琐、臃肿
- lombok就可以很好的解决。
2. 介绍
- 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修饰的字段之外带有各参数的构造器方法。 |
3. 使用
(1) 使用
-
依赖:
<!-- lombok工具包依赖 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
-
使用注解形式简化实体类代码:
(2) 注意一
-
我们使用lombok时,还需要安装一个lombok的插件(idea自带)。
(3) 注意二
-
Lombok会在编译时,自动生成注解对应的java代码。