首页 > 基础资料 博客日记
【Mybatis】知识点总结
2024-09-15 11:00:06基础资料围观115次
MyBatis 是一个持久化框架(persistence framework),它简化了对数据库的访问,同时又保留了对 SQL 的控制。它在数据持久化的过程中,避免了大量的 JDBC 代码以及手动设置参数和获取结果的繁琐步骤。相比于 Hibernate 等全自动 ORM 框架,MyBatis 更轻量级且灵活,特别适用于需要手写复杂 SQL 的场景。接下来,我们将详细介绍 MyBatis 的各个方面。
目录
- MyBatis 简介
- MyBatis 的基本概念
- MyBatis 配置文件
- Mapper 文件
- Mapper 接口
- 动态 SQL
- MyBatis 与 Spring 整合
- MyBatis 进阶特性
- MyBatis 与其他持久化框架的对比
- 实战案例
1. MyBatis 简介
1.1 MyBatis 是什么?
MyBatis 是 Apache Software Foundation 旗下的一个项目,用于在 Java 应用中处理持久化层(Persistence Layer)。它通过 XML 或注解的方式将实体类和 SQL 语句进行映射,可以帮助开发者快速进行 CRUD(Create、Read、Update、Delete)操作。
1.2 MyBatis 的特点
- 轻量级:MyBatis 不需要像 Hibernate 那样的全局配置,配置简单灵活。
- SQL 控制:MyBatis 允许开发者手写 SQL,直接与数据库交互,便于处理复杂的 SQL 查询。
- 可插拔性:MyBatis 可以与其他框架(如 Spring)无缝集成。
- 动态 SQL:支持动态 SQL 生成,以适应不同的查询条件。
- 缓存支持:支持一级缓存和二级缓存,提高性能。
2. MyBatis 的基本概念
2.1 SqlSessionFactory
- 作用:负责创建
SqlSession
实例。 - 配置:通过 XML 配置文件或 Java 配置类进行构建。
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
2.2 SqlSession
- 作用:用于执行 SQL 操作,如查询、插入、更新和删除。
- 生命周期:应为每次数据库操作创建一个新的 SqlSession,并在操作完成后关闭。
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectUserById(1);
// 其他操作
session.commit(); // 提交事务
}
2.3 Mapper 接口
- 作用:定义数据库操作的接口,MyBatis 自动生成实现类。
- 配置方式:可以通过 XML 文件或注解进行配置。
public interface UserMapper {
User selectUserById(int id);
void insertUser(User user);
List<User> selectAllUsers();
}
2.4 实体类(POJO)
- 作用:与数据库表结构相对应的 Java 类。
- 要求:需要有与数据库字段相对应的属性,以及相应的 getter 和 setter 方法。
public class User {
private int id;
private String username;
private String password;
private String email;
// getter 和 setter 方法
}
3. MyBatis 配置文件
MyBatis 的配置文件是整个框架的核心,它定义了数据库连接、事务管理、Mapper 映射等。
- 作用:配置 MyBatis 的全局属性,如数据源、事务管理等。
- 文件名:通常为
mybatis-config.xml
。
3.1 环境配置
配置多个环境(development、test、production):
<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>
<environment id="production">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://production-db:3306/proddb?useSSL=false&serverTimezone=UTC"/>
<property name="username" value="prod_user"/>
<property name="password" value="prod_password"/>
</dataSource>
</environment>
</environments>
解析
default
:指定默认环境。transactionManager
:JDBC
:使用 JDBC 提供的事务管理。MANAGED
:应用服务器或 Spring 管理事务。
dataSource
:UNPOOLED
:每次请求都会创建新连接,适用于简单应用。POOLED
:使用连接池提高性能,适用于生产环境。JNDI
:使用应用服务器的数据源。
3.2 Mapper 配置
使用 XML 配置 Mapper
<mappers>
<mapper resource="com/example/mapper/UserMapper.xml"/>
</mappers>
使用注解配置 Mapper
<mappers>
<mapper class="com.example.mapper.UserMapper"/>
</mappers>
自动扫描 Mapper 包
<mappers>
<package name="com.example.mapper"/>
</mappers>
3.3 类型别名
类型别名用于简化 XML 中类的引用,可以为常用类指定简短别名。
<typeAliases>
<typeAlias type="com.example.entity.User" alias="User"/>
</typeAliases>
可以使用包扫描自动为包下的类生成别名:
<typeAliases>
<package name="com.example.entity"/>
</typeAliases>
3.4 插件配置
MyBatis 支持插件扩展,可以通过插件实现自定义功能,如日志、分页等。
<plugins>
<plugin interceptor="com.example.plugin.ExamplePlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
3.5 全局属性配置
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useGeneratedKeys" value="true"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25000"/>
</settings>
常用全局属性
cacheEnabled
:启用或禁用二级缓存。lazyLoadingEnabled
:启用或禁用延迟加载。useGeneratedKeys
:允许 JDBC 支持生成主键。defaultExecutorType
:SIMPLE
:每次执行都会打开和关闭 Statement。REUSE
:复用 Statement。BATCH
:批量执行 Statement。
defaultStatementTimeout
:设置超时时间(秒)。
3.6 自定义类型处理器
MyBatis 提供了默认类型处理器,也支持自定义处理器来处理特殊类型。
<typeHandlers>
<typeHandler javaType="java.util.Date" jdbcType="TIMESTAMP" handler="com.example.handler.DateTypeHandler"/>
</typeHandlers>
自定义类型处理器示例:
package com.example.handler;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;
public class DateTypeHandler extends BaseTypeHandler<Date> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException {
ps.setTimestamp(i, new Timestamp(parameter.getTime()));
}
@Override
public Date getNullableResult(ResultSet rs, String columnName) throws SQLException {
Timestamp timestamp = rs.getTimestamp(columnName);
return timestamp != null ? new Date(timestamp.getTime()) : null;
}
@Override
public Date getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
Timestamp timestamp = rs.getTimestamp(columnIndex);
return timestamp != null ? new Date(timestamp.getTime()) : null;
}
@Override
public Date getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
Timestamp timestamp = cs.getTimestamp(columnIndex);
return timestamp != null ? new Date(timestamp.getTime()) : null;
}
}
3.7 日志配置
MyBatis 支持多种日志框架,包括 SLF4J、Log4j、Commons Logging、JDK Logging。
使用 SLF4J
<settings>
<setting name="logImpl" value="SLF4J"/>
</settings>
使用 Log4j
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
可以在log4j.properties
中配置日志级别:
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1} - %m%n
4. Mapper 文件
Mapper 文件是 MyBatis 中的核心组件,它定义了 SQL 语句和实体类之间的映射关系。
4.1 Mapper 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">
<!-- ResultMap 定义 -->
<resultMap id="userResultMap" type="com.example.entity.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="email" column="email"/>
</resultMap>
<!-- SQL 片段 -->
<sql id="selectAllFields">
id, username, password, email
</sql>
<!-- 查询操作 -->
<select id="selectUserById" resultMap="userResultMap" parameterType="int">
SELECT <include refid="selectAllFields"/>
FROM users
WHERE id = #{id}
</select>
<!-- 插入操作 -->
<insert id="insertUser" parameterType="com.example.entity.User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO users (username, password, email)
VALUES (#{username}, #{password}, #{email})
</insert>
<!-- 更新操作 -->
<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 的命名空间,通常与 Mapper 接口的全限定名相同。resultMap
:用于定义结果集与实体类属性的映射关系。sql
:用于定义可重用的 SQL 片段。select
、insert
、update
、delete
:分别定义查询、插入、更新、删除操作。
4.2 ResultMap
ResultMap
用于将查询结果与实体类属性进行映射。
<resultMap id="userResultMap" type="com.example.entity.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<result property="email" column="email"/>
</resultMap>
id
:映射主键字段。result
:映射非主键字段。
4.3 SQL 片段
SQL 片段可以提高 SQL 语句的重用性。
<sql id="selectAllFields">
id, username, password, email
</sql>
使用 <include>
标签引入 SQL 片段:
<select id="selectUserById" resultMap="userResultMap" parameterType="int">
SELECT <include refid="selectAllFields"/>
FROM users
WHERE id = #{id}
</select>
4.4 动态 SQL
MyBatis 支持动态 SQL,可以根据不同的条件动态生成 SQL 语句。
使用 <if>
标签
<select id="selectUser" resultMap="userResultMap" parameterType="map">
SELECT <include refid="selectAllFields"/>
FROM users
WHERE 1=1
<if test="username != null">
AND username = #{username}
</if>
<if test="email != null">
AND email = #{email}
</if>
</select>
使用 <choose>
标签
<select id="selectUser" resultMap="userResultMap" parameterType="map">
SELECT <include refid="selectAllFields"/>
FROM users
<where>
<choose>
<when test="username != null">
username = #{username}
</when>
<when test="email != null">
email = #{email}
</when>
<otherwise>
id = #{id}
</otherwise>
</choose>
</where>
</select>
使用 <foreach>
标签
<select id="selectUsersByIds" resultMap="userResultMap" parameterType="list">
SELECT <include refid="selectAllFields"/>
FROM users
WHERE id IN
<foreach item="id" collection="list" open="(" separator="," close=")">
#{id}
</foreach>
</select>
使用 <trim>
标签
<trim>
标签用于动态地移除多余的 SQL 关键字,如 AND
、OR
等。
<select id="selectUser" resultMap="userResultMap" parameterType="map">
SELECT <include refid="selectAllFields"/>
FROM users
<trim prefix="WHERE" prefixOverrides="AND |OR ">
<if test="username != null">
AND username = #{username}
</if>
<if test="email != null">
AND email = #{email}
</if>
</trim>
</select>
使用<set>
标签
<set>
标签用于动态生成 SET
子句,用于 UPDATE
语句中。
<update id="updateUser" parameterType="com.example.entity.User">
UPDATE users
<set>
<if test="username != null">
username = #{username},
</if>
<if test="password != null">
password = #{password},
</if>
<if test="email != null">
email = #{email}
</if>
</set>
WHERE id = #{id}
</update>
使用 <where>
标签
<where>
标签用于动态生成 WHERE
子句,会自动去除多余的 AND
、OR
等关键字。
<select id="selectUser" resultMap="userResultMap" parameterType="map">
SELECT <include refid="selectAllFields"/>
FROM users
<where>
<if test="username != null">
AND username = #{username}
</if>
<if test="email != null">
AND email = #{email}
</if>
</where>
</select>
5. Mapper 接口
Mapper 接口是 MyBatis 的核心组件之一,它定义了数据库操作的方法。
5.1 接口定义
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);
}
5.2 注解配置
@Insert
:定义插入 SQL 语句。@Select
:定义查询 SQL 语句。@Update
:定义更新 SQL 语句。@Delete
:定义删除 SQL 语句。@Options
:用于配置附加选项,如自动生成主键。@Param
:用于指定参数名称,解决参数名不匹配的问题。
5.3 返回值类型
Mapper 接口方法的返回值类型可以是以下几种:
- 单一对象:查询返回单个结果。
- 集合:查询返回多个结果。
- 基本类型:返回单个字段值,如
int
、String
等。 void
:用于插入、更新、删除操作。
5.4 参数传递
Mapper 接口方法的参数可以是以下几种:
- 单个参数:
如基本类型、对象。
- 多个参数:可以使用
@Param
注解指定参数名称。 - 集合参数:如
List
、Map
等。
6. MyBatis 与 Spring 整合
MyBatis 可以与 Spring 框架无缝整合,通过 Spring 管理 MyBatis 的 SqlSessionFactory 和事务。
6.1 Spring 配置文件
数据源配置
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" 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"/>
</bean>
SqlSessionFactory 配置
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath*:com/example/mapper/*.xml"/>
</bean>
Mapper 接口扫描
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.example.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
6.2 Spring Java 配置
使用 Java 配置替代 XML 配置:
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.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.example.mapper")
public class MyBatisConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC");
dataSource.setUsername("root");
dataSource.setPassword("password");
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();
}
}
6.3 事务管理
配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
声明式事务管理
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.mapper.UserMapper;
import com.example.entity.User;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Transactional
public void createUser(User user) {
userMapper.insertUser(user);
}
@Transactional(readOnly = true)
public User getUserById(int id) {
return userMapper.selectUserById(id);
}
}
7. MyBatis 进阶特性
7.1 缓存机制
MyBatis 提供了一级缓存和二级缓存机制,以提高性能。
一级缓存
- 作用范围:SqlSession 级别。
- 特性:默认开启,不同 SqlSession 之间不共享。
二级缓存
- 作用范围:Mapper 级别。
- 特性:需要显式配置,可在不同 SqlSession 之间共享。
<cache/>
自定义缓存
MyBatis 支持自定义缓存,可以通过实现 Cache
接口来自定义缓存行为。
package com.example.cache;
import org.apache.ibatis.cache.Cache;
import java.util.concurrent.locks.ReadWriteLock;
public class CustomCache implements Cache {
private final String id;
public CustomCache(String id) {
this.id = id;
}
@Override
public String getId() {
return this.id;
}
@Override
public void putObject(Object key, Object value) {
// 自定义缓存实现
}
@Override
public Object getObject(Object key) {
// 自定义缓存实现
return null;
}
@Override
public Object removeObject(Object key) {
// 自定义缓存实现
return null;
}
@Override
public void clear() {
// 自定义缓存实现
}
@Override
public int getSize() {
// 自定义缓存实现
return 0;
}
@Override
public ReadWriteLock getReadWriteLock() {
return null;
}
}
配置自定义缓存:
<cache type="com.example.cache.CustomCache"/>
7.2 分页插件
MyBatis 不支持分页功能,但可以通过插件实现分页。
<plugins>
<plugin interceptor="com.example.plugin.PaginationInterceptor">
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
分页插件示例:
package com.example.plugin;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import java.sql.Connection;
import java.util.Properties;
@Intercept
s({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class PaginationInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 拦截逻辑
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
// 设置属性
}
}
7.3 拦截器
MyBatis 支持插件机制,可以通过拦截器实现自定义功能,如分页、日志记录等。
自定义拦截器
package com.example.interceptor;
import org.apache.ibatis.plugin.*;
import java.util.Properties;
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class MyInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 拦截逻辑
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
// 设置属性
}
}
配置自定义拦截器:
<plugins>
<plugin interceptor="com.example.interceptor.MyInterceptor">
<property name="propertyName" value="propertyValue"/>
</plugin>
</plugins>
7.4 日志拦截器
MyBatis 提供了日志拦截器,可以用于记录 SQL 语句执行的详细信息。
配置日志拦截器:
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
使用 Log4j 记录 SQL 日志:
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1} - %m%n
7.5 MyBatis Generator
MyBatis Generator 是一个代码生成工具,可以根据数据库表结构生成实体类、Mapper 接口和 Mapper XML 文件。
配置文件示例
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="DB2Tables" targetRuntime="MyBatis3">
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/testdb"
userId="root"
password="password"/>
<javaModelGenerator targetPackage="com.example.entity" targetProject="src/main/java"/>
<sqlMapGenerator targetPackage="com.example.mapper" targetProject="src/main/resources"/>
<javaClientGenerator type="XMLMAPPER" targetPackage="com.example.mapper" targetProject="src/main/java"/>
<table tableName="users" domainObjectName="User"/>
</context>
</generatorConfiguration>
运行 MyBatis Generator
可以通过命令行或 Maven 插件运行 MyBatis Generator。
命令行运行
java -jar mybatis-generator-core-x.x.x.jar -configfile generatorConfig.xml -overwrite
Maven 插件运行
在 pom.xml
中添加插件配置:
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<id>generate-sources</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
</build>
执行 Maven 命令:
mvn mybatis-generator:generate
8. 总结
MyBatis 是一款强大的持久层框架,提供了灵活的 SQL 映射和强大的动态 SQL 功能,能够与 Spring 框架无缝整合,支持缓存、插件、拦截器等高级特性,是 Java 开发中常用的持久层解决方案之一。
通过本文档的介绍,您可以掌握 MyBatis 的基本使用方法和高级特性,能够在项目中灵活运用 MyBatis 进行数据库操作。
参考资料
以上是关于 MyBatis 的详细介绍和使用指南,希望能够帮助您更好地理解和使用 MyBatis。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签: