MyBatis 是一个流行的 Java 数据持久化框架,它提供了对数据库操作的简化方式。与 Hibernate 等全功能 ORM 框架不同,MyBatis 不会映射 Java 对象与数据库表之间的关系,而是关注于 SQL 的编写与执行。因此,它特别适用于那些需要对 SQL 语句进行精细控制的应用程序。
本文将详细介绍如何使用 MyBatis,包括其基本配置、使用 Mapper 进行数据库操作以及与 Spring 的集成。
目录
MyBatis 简介
MyBatis 是一个优秀的持久化层框架,它主要关注于:
- SQL 语句的复用和组织:通过 XML 或注解来定义 SQL。
- 动态 SQL:支持在 SQL 中使用动态逻辑。
- 自动映射:结果集可以自动映射到 Java 对象。
- 灵活性:允许使用原始 SQL,适用于需要精确控制的数据库操作。
- 缓存支持:支持一级缓存和二级缓存。
环境准备
在开始之前,确保已经安装并配置好以下环境:
- JDK: Java 8 或更高版本
- Maven: 作为构建工具
- MySQL: 数据库示例
- IDE: IntelliJ IDEA 或 Eclipse
依赖配置
在 pom.xml
文件中添加以下依赖:
<dependencies>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- MyBatis Spring 支持 -->
<dependency>
<groupId>org.mybatis.spring</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.3.1</version>
</dependency>
<!-- MySQL JDBC 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.34</version>
</dependency>
<!-- Spring 相关依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.22</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.22</version>
</dependency>
<!-- 数据源 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.36</version>
</dependency>
</dependencies>
基本配置
1. 创建数据库和表
在 MySQL 中创建一个名为 testdb
的数据库和一个名为 users
的表:
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(50) NOT NULL,
email VARCHAR(100)
);
2. 配置 MyBatis
MyBatis 使用 XML 文件或注解来配置映射信息。下面是基本的 XML 配置文件示例:
mybatis-config.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/testdb?useSSL=false&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</dataSource>
</environment>
</environments>
<!-- 映射器配置 -->
<mappers>
<mapper resource="com/example/mapper/UserMapper.xml"/>
</mappers>
</configuration>
解析:
transactionManager
:指定事务管理器类型。常用的有JDBC
和MANAGED
。dataSource
:配置数据源,POOLED
表示使用连接池。mappers
:指定 Mapper 映射文件的路径。
3. 编写实体类
User.java
package com.example.entity;
public class User {
private Integer id;
private String username;
private String password;
private String email;
// Getters and Setters
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
4. 编写 Mapper 接口和 XML 配置文件
Mapper 接口
UserMapper.java
package com.example.mapper;
import com.example.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserMapper {
@Insert("INSERT INTO users (username, password, email) VALUES (#{username}, #{password}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insertUser(User user);
@Select("SELECT * FROM users WHERE id = #{id}")
User selectUserById(@Param("id") int id);
@Select("SELECT * FROM users")
List<User> selectAllUsers();
@Update("UPDATE users SET username = #{username}, password = #{password}, email = #{email} WHERE id = #{id}")
void updateUser(User user);
@Delete("DELETE FROM users WHERE id = #{id}")
void deleteUser(@Param("id") int id);
}
XML 配置文件
UserMapper.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.mapper.UserMapper">
<insert id="insertUser" parameterType="com.example.entity.User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO users (username, password, email)
VALUES (#{username}, #{password}, #{email})
</insert>
<select id="selectUserById" parameterType="int" resultType="com.example.entity.User">
SELECT * FROM users WHERE id = #{id}
</select>
<select id="selectAllUsers" resultType="com.example.entity.User">
SELECT * FROM users
</select>
<update id="updateUser" parameterType="com.example.entity.User">
UPDATE users
SET username = #{username},
password = #{password},
email = #{email}
WHERE id = #{id}
</update>
<delete id="deleteUser" parameterType="int">
DELETE FROM users WHERE id = #{id}
</delete>
</mapper>
解析:
namespace
:指定 Mapper 接口的完全限定名,用于与 XML 文件关联。parameterType
:指定参数类型,可以是简单类型(如int
、String
)或 Java 类。resultType
:指定返回结果类型,通常是 Java 类或简单类型。useGeneratedKeys
:设置为true
时,MyBatis 会自动获取数据库生成的主键值。
使用 XML 配置文件
在 MyBatis 中,SQL 语句可以通过 XML 文件进行配置,这是一种常见的方式。以下是如何
使用 XML 配置文件来管理数据库操作。
1. 配置 SQL 语句
在 UserMapper.xml
文件中,我们已经定义了各种 SQL 语句,接下来是如何在代码中使用它们。
2. 配置 SqlSessionFactory
SqlSessionFactory
是 MyBatis 的核心对象之一,用于创建 SqlSession
实例。我们需要通过配置文件来创建它。
MyBatisUtil.java
package com.example.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisUtil {
private static SqlSessionFactory sqlSessionFactory;
static {
String resource = "mybatis-config.xml";
try (InputStream inputStream = Resources.getResourceAsStream(resource)) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
}
3. 使用 Mapper 执行数据库操作
接下来,我们使用 MyBatisUtil
工具类来获取 SqlSession
实例,并通过 Mapper 接口执行数据库操作。
MainApp.java
package com.example;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import com.example.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class MainApp {
public static void main(String[] args) {
try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 创建用户
User user = new User();
user.setUsername("john_doe");
user.setPassword("password123");
user.setEmail("john.doe@example.com");
userMapper.insertUser(user);
sqlSession.commit(); // 提交事务
System.out.println("User created with ID: " + user.getId());
// 查询用户
User retrievedUser = userMapper.selectUserById(user.getId());
System.out.println("Retrieved User: " + retrievedUser.getUsername());
// 更新用户
retrievedUser.setPassword("new_password123");
userMapper.updateUser(retrievedUser);
sqlSession.commit();
System.out.println("User updated.");
// 查询所有用户
List<User> allUsers = userMapper.selectAllUsers();
allUsers.forEach(u -> System.out.println("User: " + u.getUsername()));
// 删除用户
userMapper.deleteUser(user.getId());
sqlSession.commit();
System.out.println("User deleted.");
}
}
}
解析:
- 获取
SqlSession
:通过MyBatisUtil.getSqlSession()
获取SqlSession
实例。 - 获取 Mapper 接口:通过
sqlSession.getMapper(UserMapper.class)
获取 Mapper 实例。 - 执行操作:调用 Mapper 接口的方法执行数据库操作,如
insertUser()
、selectUserById()
等。 - 事务管理:调用
sqlSession.commit()
提交事务,sqlSession.rollback()
回滚事务。
使用注解配置
除了使用 XML 配置文件外,MyBatis 还支持通过注解直接在 Mapper 接口中定义 SQL 语句。以下是如何使用注解进行配置。
1. 修改 Mapper 接口
在 UserMapper.java
中,我们已经通过注解定义了 SQL 语句。
package com.example.mapper;
import com.example.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserMapper {
@Insert("INSERT INTO users (username, password, email) VALUES (#{username}, #{password}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insertUser(User user);
@Select("SELECT * FROM users WHERE id = #{id}")
User selectUserById(@Param("id") int id);
@Select("SELECT * FROM users")
List<User> selectAllUsers();
@Update("UPDATE users SET username = #{username}, password = #{password}, email = #{email} WHERE id = #{id}")
void updateUser(User user);
@Delete("DELETE FROM users WHERE id = #{id}")
void deleteUser(@Param("id") int id);
}
2. 执行数据库操作
使用注解方式的执行与使用 XML 配置相同,只需调用 Mapper 接口的方法即可。
try (SqlSession sqlSession = MyBatisUtil.getSqlSession()) {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 创建用户
User user = new User();
user.setUsername("john_doe");
user.setPassword("password123");
user.setEmail("john.doe@example.com");
userMapper.insertUser(user);
sqlSession.commit(); // 提交事务
System.out.println("User created with ID: " + user.getId());
// 查询用户
User retrievedUser = userMapper.selectUserById(user.getId());
System.out.println("Retrieved User: " + retrievedUser.getUsername());
// 更新用户
retrievedUser.setPassword("new_password123");
userMapper.updateUser(retrievedUser);
sqlSession.commit();
System.out.println("User updated.");
// 查询所有用户
List<User> allUsers = userMapper.selectAllUsers();
allUsers.forEach(u -> System.out.println("User: " + u.getUsername()));
// 删除用户
userMapper.deleteUser(user.getId());
sqlSession.commit();
System.out.println("User deleted.");
}
解析:
- 使用注解配置后,SQL 语句直接嵌入在 Java 代码中,无需单独的 XML 文件。
- 注解配置更简单,但在复杂 SQL 语句中可能显得不够灵活,特别是在涉及动态 SQL 时。
与 Spring 的集成
MyBatis 可以方便地与 Spring 集成,从而简化事务管理和数据库连接管理。以下是一个简单的 MyBatis 与 Spring 的集成示例。
1. 配置 Spring 和 MyBatis
AppConfig.java
package com.example.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = "com.example")
@MapperScan("com.example.mapper") // 扫描 Mapper 接口
public class AppConfig {
@Bean
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC");
dataSource.setUsername("root");
dataSource.setPassword("password");
dataSource.setMaximumPoolSize(10);
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath*:com/example/mapper/*.xml"));
return sessionFactory.getObject();
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
解析:
@MapperScan
:用于扫描 Mapper 接口,自动生成实现类。SqlSessionFactoryBean
:用于创建SqlSessionFactory
实例。HikariDataSource
:配置数据源,使用 HikariCP 作为连接池。
2. 使用 Spring 的方式调用 MyBatis
在 Spring 环境中,可以通过依赖注入的方式来获取 Mapper 接口实例。
UserService.java
package com.example.service;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Transactional
public void createUser(User user) {
userMapper.insertUser(user);
}
public User getUserById(int id) {
return userMapper.selectUserById(id);
}
public List<User> getAllUsers() {
return userMapper.selectAllUsers();
}
@Transactional
public void updateUser(User user) {
userMapper.updateUser(user);
}
@Transactional
public void deleteUser(int id) {
userMapper.deleteUser(id);
}
}
解析:
@Service
:标识业务层组件。@Transactional
:在方法级别或类级别启用事务管理
。
3. Spring Boot 集成 MyBatis 示例
如果你使用 Spring Boot,可以更加简化配置过程。以下是一个简单的 Spring Boot 集成 MyBatis 的示例。
pom.xml
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Spring Boot MyBatis Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Spring Boot Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis.mapper-locations=classpath:com/example/mapper/*.xml
Application.java
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
4. 使用 Spring Boot 进行操作
在 Spring Boot 环境中,操作与 Spring 的方式相似,可以直接使用依赖注入的方式来调用服务。
UserServiceTest.java
package com.example;
import com.example.entity.User;
import com.example.service.UserService;
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
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testCreateUser() {
User user = new User();
user.setUsername("jane_doe");
user.setPassword("secret");
user.setEmail("jane.doe@example.com");
userService.createUser(user);
}
@Test
public void testGetUserById() {
User user = userService.getUserById(1);
System.out.println("User: " + user.getUsername());
}
@Test
public void testGetAllUsers() {
List<User> users = userService.getAllUsers();
users.forEach(user -> System.out.println("User: " + user.getUsername()));
}
@Test
public void testUpdateUser() {
User user = userService.getUserById(1);
user.setPassword("new_secret");
userService.updateUser(user);
}
@Test
public void testDeleteUser() {
userService.deleteUser(1);
}
}
总结
MyBatis 是一个轻量级的持久化框架,提供了对 SQL 的良好支持和灵活性。通过本文,我们了解了如何配置和使用 MyBatis,包括:
- 基本配置和使用
- XML 和注解方式的配置
- 与 Spring 的集成
- Spring Boot 环境中的使用
MyBatis 在需要手动编写 SQL 和复杂查询的场景中非常有用,同时它也能够与 Spring 和 Spring Boot 无缝集成,从而提供更强大的数据访问解决方案。希望本文能帮助你快速上手 MyBatis,并在实际项目中发挥其作用。