什么是 MyBatis
在对一项技术进行深入学习前,我们应该先对它有个初步的认识。MyBatis 是一个 Java 持久层框架,用于简化数据库的操作。它通过 XML 或注解的方式配置和映射原始类型、接口和 Java POJO
(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
在此之前,如果直接使用 JDBC 进行数据库操作,我们也可以轻松完成一些简单的任务,但是当数据量越来越大,业务越来越复杂,这种方式会带来很多困难和挑战,比如:
- SQL语句的硬编码:使用JDBC时,SQL语句通常是直接在Java代码中编写的,这可能导致代码和SQL逻辑的紧密耦合,使得维护和升级变得困难。
- 结果集的处理繁琐:JDBC要求开发者手动处理结果集(ResultSet),包括从结果集中检索数据、将其转换为Java对象等。这个过程可能相当繁琐,特别是对于复杂的数据结构或大量数据的处理。
- 数据库连接的频繁开启与关闭:JDBC中,数据库连接(Connection)是宝贵的资源,需要妥善管理
- 事务管理复杂:在使用JDBC进行数据库操作时,事务的管理(如提交和回滚)需要开发者手动控制,这要求开发者对数据库事务有深入的理解。
- 动态SQL语句构建困难:在复杂的业务逻辑中,经常需要根据不同的条件动态地构建SQL语句。直接使用JDBC时,这通常需要编写复杂的逻辑来拼接SQL字符串,这不仅容易出错,还可能增加SQL注入的风险。
下面将会展示使用 JDBC 操作 MySQL 数据库
使用 JDBC 操作数据库
首先,使用 Maven 创建项目,并引入相关依赖
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.4.0</version>
</dependency>
接下来,在本地连接数据库,建立测试数据表 user
并插入测试数据
# 创建测试数据库 mybatis_learn
create database if not exists `mybatis_learn`;
use `mybatis_learn`;
# 创建user表
create table if not exists `user`
(
`id` bigint primary key not null auto_increment comment 'id',
`username` varchar(20) not null comment '用户名',
`password` varchar(20) not null comment '密码'
);
# 插入数据
insert into `user`(`username`, `password`)
values ('admin', '123456');
insert into `user`(`username`, `password`)
values ('user1', '123456');
insert into `user`(`username`, `password`)
values ('user2', '123456');
可以看到,数据已经插入成功
接下来我们还要进行一些准备工作,要创建一个 User
实体类来对应 user
表中的各个数据,方便我们后续进行解析
package com.nx.domain;
import lombok.Data;
/**
* user实体类
*
* @author nx-xn2002
* @date 2024-08-02
*/
@Data
public class User {
private Long id;
private String username;
private String password;
}
接下来,通过加载驱动 -> 获取连接 -> 获取statement并构造sql语句 -> 执行查询并获取结果集 -> 解析结果集 -> 打印结果 -> 关闭连接这一系列行为,我们可以将刚刚创建的数据库里的内容查询出来
/**
* 直接使用 jdbc 操作数据库
*
* @author nx-xn2002
* @date 2024-08-02
*/
public class QueryWithJdbc {
static String url = "jdbc:mysql://localhost:3306/mybatis_learn";
static String userName = "root";
static String password = "123456";
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 获取连接
Connection connection = DriverManager.getConnection(url, userName, password);
// 获取预编译的 statement
PreparedStatement preparedStatement = connection.prepareStatement("select * from user");
// 执行查询
ResultSet resultSet = preparedStatement.executeQuery();
List<User> users = new ArrayList<>();
// 遍历结果集
while (resultSet.next()) {
User user = new User();
user.setId(resultSet.getLong("id"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
users.add(user);
}
users.forEach(System.out::println);
connection.close();
}
}
可以看到,虽然使用 JDBC 可以正常操作数据库,但是还是存在较多问题,比如每次获取结果,都要去手动进行实体类对象的值的设定,代码中存在大量的硬编码的 sql 语句,频繁开启关闭数据库连接,这些都会大大降低我们的开发效率。
对于以上问题,MyBatis 在 java 和 sql 之间提供了更灵活的映射方案,MyBatis 将 sql 语句和方法实现,直接写到 xml 文件中,实现和 java 程序解耦
MyBatis 操作数据库
首先,我们引入 MyBatis 依赖
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.16</version>
</dependency>
要想正常使用 MyBatis,我们需要几个文件,首先是配置文件src/main/resources/mybatis-config.xml
,在这里面我们可以配置数据库连接以及选定项目中的 xml
映射文件,如下所示
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_learn"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 引入映射文件,如果有多个文件,则在此处添加 -->
<mappers>-->
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
接下来就是刚刚提到的映射文件,此处也就是配置文件中的UserMapper.xml
,在这里面可以定义一系列的 sql 语句和对应的方法名,此处我就写了listAll
,以此完成前面的查找所有用户的功能
<?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.nx.mapper.UserMapper">
<!-- 定义查询所有用户的 SQL 语句-->
<select id="listAll" resultType="com.nx.domain.User">
SELECT * FROM user;
</select>
</mapper>
可以看到,要想让 MyBatis 能够完成 ORM 的转化工作,我们还需要定义一个实体类,在这里我们复用前面创建的 com.nx.domain.User
类
接下来要创建一个与 UserMapper.xml
映射文件对应的映射接口,这样才能正常进行调用,这个接口就是映射文件中<mapper namespace="com.nx.mapper.UserMapper">
里提到的 UserMapper
接口
package com.nx.mapper;
import com.nx.domain.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* user mapper
*
* @author nx-xn2002
* @date 2024-08-02
*/
@Mapper
public interface UserMapper {
/**
* 查询所有用户
*
* @return {@link List }<{@link User }>
* @author nx-xn2002
*/
List<User> listAll();
}
接口中我们需要创建与映射文件中相对应的方法声明,在这里,@Mapper
注解仅作为标识,没有特殊作用,只有在 Spring Boot 等项目中具有实际作用。
接下来我们可以写一个简单程序来检验一下刚刚完成的内容
package com.nx;
import com.nx.domain.User;
import com.nx.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* 使用 MyBatis 操作数据库
*
* @author nx-xn2002
* @date 2024-08-02
*/
public class QueryWithMyBatis {
public static void main(String[] args) throws IOException {
// 加载核心配置文件路径
String resource = "mybatis-config.xml";
//通过SqlSessionFactor的openSqlSession()方法获取SqlSession对象
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//使用SqlSession.getMapper()来获取UserMapper接口对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//调用接口方法
List<User> users = mapper.listAll();
users.forEach(System.out::println);
sqlSession.close();
}
}
打印结果如下:
可以看到,在刚刚的代码里,我们已经成功完成了 java 与 sql 语句的解耦合,同时,项目中可以很轻松的获取到查询结果的实体类对象,大大减少了冗余代码。以上就是 MyBatis 的简单应用。