MyBatis全解

目录

一, MyBatis 概述

1.1-介绍 MyBatis 的历史和发展

1.2-MyBatis 的特点和优势

1.3-MyBatis 与 JDBC 的对比

1.4-MyBatis 与其他 ORM 框架的对比

二, 快速入门

2.1-环境搭建

2.2-第一个 MyBatis 应用程序

2.3-配置文件详解 (mybatis-config.xml)

2.4-Mapper 文件详解 (xxxMapper.xml)

三,核心概念

3.1-Session 和 SqlSessionFactory

3.2-映射器 (Mapper) 接口和 XML 映射文件

3.3-SQL 语句的执行流程

3.4-结果映射 (Result Mapping)

四,动态 SQL

4.1-if, choose, when, otherwise

4.2-trim, where, set

4.3-foreach

4.4-bind

五,参数处理

5.1-单个参数

5.2-多个参数

5.3-Map 参数

5.4-POJO 参数

六,类型处理器 (Type Handlers)

6.1-内置类型处理器

6.2-自定义类型处理器

七,高级特性

7.1-关联映射 (一对一、多对一)

7.2-集合映射 (一对多)

7.3-嵌套查询和嵌套结果

7.4-缓存机制 (一级缓存和二级缓存)

7.5-事务管理

八,插件机制

8.1-日志插件

8.2-分页插件

九,集成 Spring

9.1-Spring 中的 MyBatis 配置

9.2-使用 Spring 管理 MyBatis 的 SqlSessionFactory 和 Mapper

十, 最佳实践

10.1-代码组织结构

10.2-异常处理

10.3-测试策略

十一,实战案例

十二,社区和扩展

12.1-MyBatis 生态系统

12.2-第三方工具集成

12.3-社区资源和文档


一, MyBatis 概述

1.1-介绍 MyBatis 的历史和发展

  • 起源:MyBatis 的前身是 iBatis,最初由 Clinton Begin 在2001年创建。
  • 发展:2008年左右,iBatis 被捐赠给了 Apache 软件基金会,并更名为 MyBatis。
  • 版本演变:MyBatis 3.x 版本引入了大量的改进和新特性,成为目前最广泛使用的版本。
  • 社区与生态:MyBatis 拥有活跃的社区和丰富的插件生态系统,包括 MyBatis Generator、MyBatis Plus 等工具。

1.2-MyBatis 的特点和优势

  • 轻量级:MyBatis 相对于其他 ORM 框架来说更为轻量,易于上手且灵活性高。
  • SQL 语句编写:允许直接编写 SQL 语句,提供更高的定制能力和优化空间。
  • 结果映射:提供强大的结果映射机制,能够灵活地处理复杂的数据结构。
  • 动态 SQL:支持动态 SQL 语法,可以根据条件生成不同的 SQL 语句。
  • 插件机制:支持插件扩展,可以方便地添加日志记录、分页等功能。
  • 与 Spring 的良好集成:能够很好地与 Spring 框架集成,提供依赖注入和事务管理等功能。

1.3-MyBatis 与 JDBC 的对比

  • 封装性:MyBatis 对 JDBC 进行了封装,避免了直接与 JDBC API 交互的繁琐步骤。

  • 资源管理:MyBatis 自动管理 SQL 会话,减少了资源泄漏的风险。

  • 错误处理:MyBatis 提供更友好的异常处理机制,使得错误定位更加容易。

  • SQL 语句编写:MyBatis 支持直接编写 SQL 语句,而 JDBC 需要程序员自行构建 SQL 语句。

  • 结果映射:MyBatis 提供了自动化的结果映射机制,使得数据转换更为简单。

1.4-MyBatis 与其他 ORM 框架的对比

Hibernate:

  • 全自动 vs 半自动:Hibernate 是全自动的 ORM 框架,而 MyBatis 是半自动的。
  • 易用性:Hibernate 提供了更多的自动化特性,如懒加载、缓存等。
  • 性能:MyBatis 因为更接近 SQL 的控制,所以可能在某些场景下有更好的性能。

JPA (Java Persistence API):

  • 标准 vs 实现:JPA 是一种规范,而 Hibernate 是 JPA 的实现之一;MyBatis 则是一种具体的框架。
  • API 使用:JPA 使用面向对象的方式,而 MyBatis 更偏向于 SQL 语句的编写。

Spring Data JPA:

  • 集成度:Spring Data JPA 与 Spring 集成度更高,提供了更多的便捷方法。
  • 灵活性:MyBatis 在编写 SQL 方面提供了更大的灵活性。


二, 快速入门

2.1-环境搭建

1.安装 JDK

  • 确保已安装 JDK 1.8 或以上版本。
  • 设置环境变量 JAVA_HOME。

2.安装 Maven (可选)

  • 如果使用 Maven 管理项目依赖,则需安装 Maven。
  • 设置环境变量 M2_HOME 和 MAVEN_HOME。

3.创建 Maven 项目

  • 使用 IntelliJ IDEA 或 Eclipse 创建一个新的 Maven 项目。
  • 添加 MyBatis 和 MySQL 的依赖到 pom.xml 文件中。
   <dependencies><!-- MyBatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.11</version></dependency><!-- MySQL Connector/J --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.32</version></dependency><!-- Logging --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.36</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>1.7.36</version></dependency></dependencies>

4.配置 MySQL 数据库

  • 创建数据库和表。
  • 配置数据库连接信息。

5.创建实体类

  • 根据数据库表结构创建对应的 Java 实体类。

6.创建 MyBatis 配置文件

  • 创建 mybatis-config.xml 文件。

7.编写 Mapper 文件

  • 创建 UserMapper.xml 文件。

2.2-第一个 MyBatis 应用程序

1.创建实体类

  • 创建 User.java 实体类。
        @Data@NoArgsConstructor@AllArgsConstructor    public class User {private int id;private String name;private String email;}

2.创建 Mapper 接口

  • 创建 UserMapper.java 接口。
     import org.apache.ibatis.annotations.Select;public interface UserMapper {@Select("SELECT * FROM users WHERE id = #{id}")User getUserById(int id);}

3.创建 Mapper 文件

  • 创建 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"><select id="getUserById" resultType="com.example.entity.User">SELECT * FROM users WHERE id = #{id}</select></mapper>

4.配置文件详解 (mybatis-config.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/mydatabase?useSSL=false&amp;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>

5.编写测试类

  • 创建 UserTest.java 文件来测试 MyBatis 的基本功能。
     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;public class UserTest {public static void main(String[] args) throws IOException {InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);try (SqlSession sqlSession = sqlSessionFactory.openSession()) {UserMapper userMapper = sqlSession.getMapper(UserMapper.class);User user = userMapper.getUserById(1);System.out.println(user);}}} 

2.3-配置文件详解 (mybatis-config.xml)

        mybatis-config.xml 是 MyBatis 的核心配置文件,用于配置 MyBatis 的运行环境以及其他各种属性。下面是 mybatis-config.xml 的详细说明:


1. 根元素 <configuration>

属性:

说明:根元素,包含了所有子元素。

2.<properties>

属性:

  • resource:指定外部 properties 文件的位置。
  • url:指定外部 properties 文件的 URL。
  • defaultPrefix:指定默认前缀,用于在 properties 文件中区分默认值。

说明:

  • 用于读取外部的 properties 文件,可以用来配置数据库连接信息等。

3. <settings>

属性:
说明:包含一系列的设置项,用于改变 MyBatis 的行为。

4. <typeAliases>

属性:
说明:用于配置别名,可以简化 Java 类型的引用。

5. <typeHandlers>

属性:
说明:用于配置自定义的类型处理器,可以处理特定类型的转换。

6. <objectFactory>

属性:
说明:用于配置 MyBatis 创建新实例的方式,默认使用 Java 默认构造器。

7. <plugins>

属性:
说明:用于配置 MyBatis 的插件,可以增强或修改 MyBatis 的行为。

8. <environments>

属性:
说明:用于配置不同的环境,如开发、测试、生产等。

<environment>:表示一个具体的环境配置。

        属性:
                id:环境标识符。
        子元素:
                <transactionManager>:配置事务管理器。
                        属性:
                                type:事务管理器类型,如 JDBC、MANAGED。
                <dataSource>:配置数据源。
                        属性:
                                type:数据源类型,如 UNPOOLED、POOLED、JNDI。
                        子元素:
                                <property>:配置数据源的属性,如 url、username、password。

9. <databaseIdProvider>

属性:
说明:用于配置数据库 ID 提供者,可以用于区分不同的数据库方言。

10. <mappers>

属性:
说明:用于配置 Mapper 接口或 Mapper XML 文件的位置。
        <mapper>:配置单个 Mapper 文件或接口。
                属性:
                        resource:指定 Mapper 文件的资源路径。
                        url:指定 Mapper 文件的 URL。
                        class:指定 Mapper 接口的全限定类名。
        <package>:批量注册指定包下的所有 Mapper 接口。
                属性:
                        name:指定包名。

<?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><properties resource="db.properties"/><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><typeAliases><typeAlias alias="User" type="com.example.entity.User"/></typeAliases><typeHandlers><typeHandler handler="com.example.handler.MyTypeHandler"/></typeHandlers><objectFactory><property name="defaultScope" value="prototype"/></objectFactory><plugins><plugin interceptor="com.example.interceptor.MyInterceptor"><property name="someProperty" value="100"/></plugin></plugins><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments><mappers><mapper resource="com/example/mapper/UserMapper.xml"/><mapper class="com.example.mapper.UserMapper"/><package name="com.example.mapper"/></mappers>
</configuration>

2.4-Mapper 文件详解 (xxxMapper.xml)

xxxMapper.xml 是 MyBatis 的映射文件,用于定义 SQL 语句和结果映射规则。下面是 xxxMapper.xml 的详细说明:


1. 根元素 <mapper>

属性:namespace:指定 Mapper 接口的全限定类名或唯一标识符。
说明:根元素,包含了所有的映射语句。

2. <insert>

属性:

  • id:映射语句的唯一标识符。
  • parameterType:传入参数的类型。
  • useGeneratedKeys:是否使用主键自动生成。
  • keyProperty:指定自动生成的主键值放入哪个字段。
  • keyColumn:指定自动生成的主键值的列名。

说明:定义插入语句。

3. <update>

属性:

  • id:映射语句的唯一标识符。
  • parameterType:传入参数的类型。

说明:定义更新语句。

4. <delete>

属性:

  • id:映射语句的唯一标识符。
  • parameterType:传入参数的类型。

说明:定义删除语句。

5. <select>

属性:

  • id:映射语句的唯一标识符。
  • parameterType:传入参数的类型。
  • resultType:返回结果的类型。
  • resultSetType:结果集类型,如 FORWARD_ONLY、SCROLL_INSENSITIVE、SCROLL_SENSITIVE。

说明:定义查询语句。

6. <resultMap>

属性:

  • id:映射语句的唯一标识符。
  • type:返回结果的类型。

说明:定义结果映射规则,可以用于复杂的映射逻辑。

7. <sql>

属性:id:SQL 片段的唯一标识符。
说明:定义可重用的 SQL 片段。

8. <include>

属性:refid:引用 <sql> 元素的 ID。
说明:引用 <sql> 元素定义的 SQL 片段。

9. 动态 SQL

元素:
<if>, <choose>, <when>, <otherwise>,<where>,<set>,<foreach>,<bind>
说明:用于构建动态 SQL 语句。

<?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"><select id="selectUserById" parameterType="int" resultType="User">SELECT * FROM users WHERE id = #{id}</select><insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">INSERT INTO users (name, email) VALUES (#{name}, #{email})</insert><update id="updateUser" parameterType="User">UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}</update><delete id="deleteUser" parameterType="int">DELETE FROM users WHERE id = #{id}</delete>
</mapper>

三,核心概念

3.1-Session 和 SqlSessionFactory

Session 和 SqlSessionFactory
SqlSessionFactory:

SqlSessionFactory 是 MyBatis 中最重要的对象之一,它是线程安全的,可以在应用程序的生命周期内存在一个实例。
它的主要作用是创建 SqlSession 对象。
通常情况下,SqlSessionFactory 会在应用程序启动时创建一次,并在整个应用的生命周期中复用。

SqlSession:

SqlSession 是 MyBatis 的主要 API,它代表了一次数据库会话。
每当需要执行 SQL 语句时,都需要从 SqlSessionFactory 中获取一个 SqlSession 实例。
SqlSession 是线程不安全的,因此每次使用后应该关闭它。
SqlSession 提供了执行 SQL 语句的方法,包括 insert、update、delete select。

3.2-映射器 (Mapper) 接口和 XML 映射文件

Mapper 接口:

Mapper 接口是 Java 接口,它定义了 SQL 语句的抽象方法。
这些方法的名称和参数类型被 MyBatis 用来定位相应的 SQL 语句。
当调用 Mapper 接口的方法时,MyBatis 会执行相应的 SQL 语句并返回结果。

XML 映射文件:

XML 映射文件包含了具体的 SQL 语句结果映射规则
映射文件中的每个 <mapper> 标签都有一个 namespace 属性,该属性的值通常是 Mapper 接口的全限定名。
映射文件中的 <select>、<insert>、<update> 和 <delete> 标签定义了 SQL 语句和参数类型。
<resultMap> 标签用于定义结果映射规则,它指定了如何将数据库结果集映射到 Java 对象。

3.3-SQL 语句的执行流程

1.获取 SqlSessionFactory:
通过 SqlSessionFactoryBuilder 构建一个 SqlSessionFactory 实例。
2.打开 SqlSession:
通过 SqlSessionFactory.openSession() 方法获取一个 SqlSession 实例。
3.获取 Mapper:
通过 SqlSession.getMapper() 方法获取一个 Mapper 接口的实现。
4.执行 SQL 语句:
调用 Mapper 接口中定义的方法来执行 SQL 语句。
MyBatis 会根据方法签名查找对应的 SQL 语句并执行。
5.处理结果:
如果是查询语句,MyBatis 会根据 <resultMap> 或 resultType 属性将结果集映射到 Java 对象。
如果是 DML 语句(如 insert、update、delete),则返回影响的行数。
6.提交或回滚:
如果需要,调用 SqlSession.commit() 提交事务。
如果出现错误,调用 SqlSession.rollback() 回滚事务。
7.关闭 SqlSession:
最后,调用 SqlSession.close() 关闭会话。

3.4-结果映射 (Result Mapping)

概述:
结果映射是 MyBatis 的核心特性之一,它允许开发者定义如何将 SQL 查询结果映射到 Java 对象。
通过 <resultMap> 标签可以定义复杂的映射规则,包括一对一一对多多对多的关系映射。
基本映射:

  • 在 <resultMap> 中,使用 <id> 和 <result> 标签来定义列到 Java 属性的映射。
  • <id> 通常用于主键字段,而 <result> 用于其他字段。
  • 可以指定 column 和 property 属性来关联数据库列名和 Java 属性名。

高级映射:

  • 对于复杂的一对多或一对多关系,可以使用 <association> 和 <collection> 标签。<association> 用于一对一关系,而 <collection> 用于一对多关系。
  • 这些标签支持嵌套查询和嵌套结果映射,从而可以处理复杂的对象图。

四,动态 SQL

4.1-if, choose, when, otherwise

if:

if:用于根据条件判断是否添加某个 SQL 子句。
属性:test: 表达式,如果为 true,则包含此元素内的 SQL 语句;否则忽略。
示例:

    <if test="name != null">AND name = #{name}</if>

 choose, when, otherwise:

choose, when, otherwise:
类似于 Java 中的 switch-case 语句,用于多个条件的选择。
choose 开始选择结构,when 定义一个条件,otherwise 定义默认情况。
示例:
 

    <choose><when test="name != null">AND name = #{name}</when><when test="age != null">AND age = #{age}</when><otherwise>ORDER BY id DESC</otherwise></choose>

4.2-trim, where, set

trim, where, set:

trim:用于去除多余的前缀或后缀,例如去除多余的 AND 或 OR。
属性:

  • prefix: 前缀字符串。
  • suffix: 后缀字符串。
  • prefixOverrides: 指定需要去除的前缀字符串。
  • suffixOverrides: 指定需要去除的后缀字符串。

示例:

    <trim prefix="WHERE" suffixOverrides="AND"><if test="name != null">name = #{name} AND</if><if test="age != null">age = #{age} AND</if></trim>

 where:

where:
用于自动处理 WHERE 子句的添加和多余的 AND 或 OR 的去除。
示例:

    <where><if test="name != null">name = #{name}</if><if test="age != null">AND age = #{age}</if></where>

 set:

set:
用于自动处理 SET 子句的添加和多余的逗号的去除。
示例:

    <set><if test="name != null">name = #{name},</if><if test="age != null">age = #{age},</if></set>

4.3-foreach

foreach:

foreach:
用于遍历集合或数组,并生成多个 SQL 子句。
属性:

  • collection: 集合或数组的名称。
  • item: 遍历时使用的变量名称。
  • index: 集合索引的变量名称。
  • open: 开始符号。
  • close: 结束符号。
  • separator: 分隔符。

示例:

    <foreach collection="ids" item="id" open="(" close=")" separator=",">#{id}</foreach>

4.4-bind

bind:

bind:
用于绑定表达式的值到一个变量。
属性:

  • name: 绑定变量的名称。
  • value: 绑定的表达式。

示例:

    <bind name="searchName" value="'%' + name + '%'"/><select id="findByName" resultType="User">SELECT * FROM users WHERE name LIKE #{searchName}</select>

五,参数处理

5.1-单个参数

直接使用:
当只有一个参数时,可以直接使用 #{} 占位符。
示例:

    <select id="findUserById" parameterType="int" resultType="com.example.entity.User">SELECT * FROM users WHERE id = #{id}</select>

使用 @Param 注解:
即使只有一个参数,也可以使用 @Param 注解来明确参数名称。
示例:

    <select id="findUserById" parameterType="int" resultType="com.example.entity.User">SELECT * FROM users WHERE id = #{id}</select> 

5.2-多个参数

使用 @Param 注解:
当有多个参数时,可以使用 @Param 注解来指定每个参数的名称。
示例:

JAVA:

 List<User> findUsers(@Param("name") String name, @Param("age") Integer age);

XML:

    <select id="findUsers" parameterType="map" resultType="com.example.entity.User">SELECT * FROM users<where><if test="name != null">name = #{name}</if><if test="age != null">AND age = #{age}</if></where></select>

使用 Map 参数:
也可以直接传递一个 Map 对象作为参数。
示例: 

JAVA:

    List<User> findUsers(Map<String, Object> params);

XML:

    <select id="findUsers" parameterType="map" resultType="com.example.entity.User">SELECT * FROM users<where><if test="name != null">name = #{name}</if><if test="age != null">AND age = #{age}</if></where></select>

5.3-Map 参数

直接传递 Map:
当需要传递多个参数时,可以使用 Map 对象。
示例:

JAVA:

    List<User> findUsersByParams(Map<String, Object> params);

XML:

    <select id="findUsersByParams" parameterType="map" resultType="com.example.entity.User">SELECT * FROM users<where><if test="name != null">name = #{name}</if><if test="age != null">AND age = #{age}</if></where></select>

5.4-POJO 参数

使用 POJO 对象:
当参数是一个 Java 对象时,可以使用该对象的属性作为 SQL 语句中的参数。
示例:

    public class UserSearchCriteria {private String name;private Integer age;// Getters and Setters}List<User> findUsers(UserSearchCriteria criteria);

XML:

    <select id="findUsers" parameterType="com.example.entity.UserSearchCriteria" resultType="com.example.entity.User">SELECT * FROM users<where><if test="name != null">name = #{name}</if><if test="age != null">AND age = #{age}</if></where></select>

六,类型处理器 (Type Handlers)

6.1-内置类型处理器

MyBatis 提供了一系列内置的类型处理器,用于处理常见的 Java 类型和 JDBC 类型之间的转换。这些内置类型处理器包括但不限于:
基本数据类型:

  • BooleanTypeHandler
  • ByteTypeHandler
  • ShortTypeHandler
  • IntegerTypeHandler
  • LongTypeHandler
  • FloatTypeHandler
  • DoubleTypeHandler
  • BigDecimalTypeHandler
  • StringTypeHandler
  • NStringTypeHandler
  • DateTypeHandler
  • TimestampTypeHandler
  • BlobTypeHandler
  • ClobTypeHandler

其他类型:

  • EnumTypeHandler
  • EnumOrdinalTypeHandler
  • LocalDateTimeTypeHandler
  • LocalDateTypeHandler
  • LocalTimeTypeHandler

这些内置类型处理器通常不需要额外配置,因为 MyBatis 会自动识别并使用它们。

6.2-自定义类型处理器

对于一些特殊的数据类型,如自定义的 Java 类或枚举类型,可能需要自定义类型处理器来实现转换逻辑。
创建自定义类型处理器:
创建一个类实现 org.apache.ibatis.type.TypeHandler 接口。
实现 setParameter 和 getResult 方法。
可以使用 @MappedJdbcTypes 和 @MappedTypes 注解来指定处理器支持的 JDBC 类型和 Java 类型。
注册自定义类型处理器:
在 MyBatis 的配置文件中注册类型处理器。
或者使用 typeHandlers 元素来注册自定义类型处理器。

七,高级特性

7.1-关联映射 (一对一、多对一)

在关联映射中,你需要处理两个实体之间的关系,例如一对多或多对一的关系。MyBatis 支持通过 <association> 和 <collection> 标签来处理这些关系。
一对一关联映射:
使用 <association> 标签来处理两个实体之间的一对一关系。
示例:

    <resultMap id="UserWithProfileResultMap" type="com.example.entity.User"><id property="id" column="user_id"/><result property="username" column="username"/><association property="profile" javaType="com.example.entity.Profile"><id property="id" column="profile_id"/><result property="bio" column="bio"/></association></resultMap>

7.2-集合映射 (一对多)

多对一关联映射:
使用 <association> 标签来处理两个实体之间的多对一关系。
示例:

    <resultMap id="OrderWithCustomerResultMap" type="com.example.entity.Order"><id property="id" column="order_id"/><result property="orderNumber" column="order_number"/><association property="customer" javaType="com.example.entity.Customer"><id property="id" column="customer_id"/><result property="name" column="name"/></association></resultMap>

当需要处理一对多的关系时,可以使用 <collection> 标签来处理。
一对多关联映射:
使用 <collection> 标签来处理两个实体之间的一对多关系。
示例:

    <resultMap id="CustomerWithOrdersResultMap" type="com.example.entity.Customer"><id property="id" column="customer_id"/><result property="name" column="name"/><collection property="orders" ofType="com.example.entity.Order"><id property="id" column="order_id"/><result property="orderNumber" column="order_number"/></collection></resultMap>

7.3-嵌套查询和嵌套结果

在某些情况下,你可能希望先执行一次查询来获取主实体,然后再基于主实体的结果执行额外的查询来获取关联实体。这可以通过嵌套查询和嵌套结果来实现。
嵌套查询:
使用 <association> 或 <collection> 标签中的 select 属性来指定另一个查询 ID。
示例:

    <resultMap id="CustomerWithOrdersResultMap" type="com.example.entity.Customer"><id property="id" column="customer_id"/><result property="name" column="name"/><collection property="orders" ofType="com.example.entity.Order" select="com.example.mapper.OrderMapper.findOrdersByCustomerId"/></resultMap>

嵌套结果:

使用 <association> 或 <collection> 标签中的 column 属性来指定关联查询所需的列。
示例:

    <resultMap id="CustomerWithOrdersResultMap" type="com.example.entity.Customer"><id property="id" column="customer_id"/><result property="name" column="name"/><collection property="orders" ofType="com.example.entity.Order"><id property="id" column="order_id"/><result property="orderNumber" column="order_number"/></collection></resultMap><select id="findCustomersWithOrders" resultMap="CustomerWithOrdersResultMap">SELECT c.*, o.order_id, o.order_numberFROM customers cLEFT JOIN orders o ON c.customer_id = o.customer_id</select>

7.4-缓存机制 (一级缓存和二级缓存)

MyBatis 提供了一级缓存和二级缓存机制来提高应用程序的性能。
一级缓存:
默认开启,基于 PerSqlSession 的缓存,即同一个 SqlSession 中的两次相同的查询会从缓存中获取数据。
示例:

    try (SqlSession session = sqlSessionFactory.openSession()) {UserMapper userMapper = session.getMapper(UserMapper.class);User user = userMapper.findUserById(1);  // 第一次查询User user2 = userMapper.findUserById(1);  // 从缓存中获取}

二级缓存:

需要手动开启,并且默认关闭。
基于 PerNamespace 的缓存,即同一个命名空间下的所有 SQL 语句共享一个缓存。
示例:

    <cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/><select id="findUserById" parameterType="int" resultType="com.example.entity.User" useCache="true">SELECT * FROM users WHERE id = #{id}</select>

7.5-事务管理

MyBatis 支持多种事务管理方式,包括通过 JDBC 连接管理事务或集成 Spring 框架进行事务管理。
JDBC 事务管理:
在 SqlSession 中管理事务。
示例:

    try (SqlSession session = sqlSessionFactory.openSession()) {UserMapper userMapper = session.getMapper(UserMapper.class);userMapper.insertUser(new User("Alice", 30));session.commit();  // 提交事务} catch (Exception e) {session.rollback();  // 回滚事务}

Spring 事务管理:
通过 Spring 的 AOP 功能管理事务。
示例:

    @Transactionalpublic void createUser(User user) {userMapper.insertUser(user);}

八,插件机制

8.1-日志插件

日志插件可以帮助你记录 SQL 语句和参数,这对于调试和性能分析非常有用。
实现:
创建一个实现了 org.apache.ibatis.plugin.Interceptor 接口的类。
实现 intercept 方法来拦截目标对象的方法调用。
使用 @Intercepts 注解来指定要拦截的目标对象和方法。
示例:

  import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.*;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import java.util.Properties;@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})public class LoggingInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];BoundSql boundSql = mappedStatement.getBoundSql(invocation.getArgs()[1]);System.out.println("Executing SQL: " + boundSql.getSql());return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {}}

注册:
在 MyBatis 的配置文件中注册插件。
示例:

    <?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><plugins><plugin interceptor="com.example.interceptor.LoggingInterceptor"/></plugins><!-- 其他配置 --></configuration>

8.2-分页插件

分页插件可以自动修改 SQL 语句来支持分页查询。
实现:
创建一个实现了 org.apache.ibatis.plugin.Interceptor 接口的类。
实现 intercept 方法来修改 SQL 语句以支持分页。
使用 @Intercepts 注解来指定要拦截的目标对象和方法。
示例:

  import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.*;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import java.sql.Connection;import java.util.Properties;@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})public class PaginationInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];RowBounds rowBounds = (RowBounds) invocation.getArgs()[2];Connection connection = (Connection) invocation.getArgs()[3];BoundSql boundSql = mappedStatement.getBoundSql(invocation.getArgs()[1]);String originalSql = boundSql.getSql();// Modify the SQL for paginationString paginatedSql = modifySqlForPagination(originalSql, rowBounds);// Update the BoundSql with the modified SQLBoundSql newBoundSql = new BoundSql(mappedStatement.getConfiguration(), paginatedSql, boundSql.getParameterMappings(), boundSql.getParameterObject());mappedStatement.setBoundSql(newBoundSql);return invocation.proceed();}private String modifySqlForPagination(String originalSql, RowBounds rowBounds) {// Implement pagination logic based on the database dialect// Example for MySQL:int offset = rowBounds.getOffset();int limit = rowBounds.getLimit();return originalSql + " LIMIT " + offset + ", " + limit;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {}}

注册:
在 MyBatis 的配置文件中注册插件。
示例:

    <?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><plugins><plugin interceptor="com.example.interceptor.PaginationInterceptor"/></plugins><!-- 其他配置 --></configuration>

8.3-性能监控插件

性能监控插件可以用来记录 SQL 执行的时间和其他性能指标。
实现:
创建一个实现了 org.apache.ibatis.plugin.Interceptor 接口的类。
实现 intercept 方法来记录 SQL 执行的时间。
使用 @Intercepts 注解来指定要拦截的目标对象和方法。
示例:

  import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.*;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import java.util.Properties;@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})public class PerformanceMonitorInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {long start = System.currentTimeMillis();Object result = invocation.proceed();long end = System.currentTimeMillis();long executionTime = end - start;MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];BoundSql boundSql = mappedStatement.getBoundSql(invocation.getArgs()[1]);System.out.println("Execution time: " + executionTime + " ms for SQL: " + boundSql.getSql());return result;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {}}

注册:
在 MyBatis 的配置文件中注册插件。
示例:

    <?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><plugins><plugin interceptor="com.example.interceptor.PerformanceMonitorInterceptor"/></plugins><!-- 其他配置 --></configuration>

解释
LoggingInterceptor:
实现了 Interceptor 接口。
使用 @Intercepts 注解指定了要拦截的 Executor 类的 update 和 query 方法。
在 intercept 方法中记录了 SQL 语句。


PaginationInterceptor:
实现了 Interceptor 接口。
使用 @Intercepts 注解指定了要拦截的 Executor 类的 query 方法。
在 intercept 方法中修改了 SQL 语句以支持分页。
修改了 BoundSql 对象以反映新的 SQL 语句。


PerformanceMonitorInterceptor:
实现了 Interceptor 接口。
使用 @Intercepts 注解指定了要拦截的 Executor 类的 update 和 query 方法。
在 intercept 方法中记录了 SQL 执行的时间。 

九,集成 Spring

9.1-Spring 中的 MyBatis 配置

首先确保你的项目包含了 Spring 和 MyBatis 相关的依赖。如果你使用 Maven,可以在 pom.xml 文件中添加如下依赖:

<!-- Spring 框架 -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version>
</dependency><!-- MyBatis -->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version>
</dependency><!-- 数据库驱动,例如MySQL -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.driver.version}</version>
</dependency>

9.2-使用 Spring 管理 MyBatis 的 SqlSessionFactory 和 Mapper

在 Spring 配置文件(如 applicationContext.xml 或使用 Java Config 类)中配置数据源和 SqlSessionFactory。

XML 配置示例:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mydb?useSSL=false&amp;serverTimezone=UTC"/><property name="username" value="yourUsername"/><property name="password" value="yourPassword"/>
</bean><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><!-- 配置 MyBatis 的配置文件位置 --><property name="configLocation" value="classpath:mybatis-config.xml"/><!-- 配置 Mapper 文件的位置 --><property name="mapperLocations" value="classpath*:mapper/*.xml"/>
</bean>

Java Config 示例:

@Configuration
public class DatabaseConfig {@Value("${spring.datasource.url}")private String dbUrl;@Value("${spring.datasource.username}")private String username;@Value("${spring.datasource.password}")private String password;@Beanpublic DataSource dataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl(dbUrl);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}@Beanpublic SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSource);factoryBean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));return factoryBean.getObject();}
}

配置 MapperScannerConfigurer

为了自动扫描和注册 Mapper 接口,你需要配置 MapperScannerConfigurer。这一步可以通过 XML 或 Java Config 完成。

XML 配置示例:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.yourcompany.yourproject.mapper"/><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

Java Config 示例:

@Configuration
public class MyBatisConfig {@Autowiredprivate SqlSessionFactory sqlSessionFactory;@Beanpublic MapperScannerConfigurer mapperScannerConfigurer() {MapperScannerConfigurer configurer = new MapperScannerConfigurer();configurer.setBasePackage("com.yourcompany.yourproject.mapper");configurer.setSqlSessionFactoryBeanName("sqlSessionFactory");return configurer;}
}

使用 Mapper 接口

在你的服务类中,直接注入 Mapper 接口,Spring 会自动创建代理对象并管理它的生命周期。

@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public List<User> getAllUsers() {return userMapper.selectAll();}
}

十, 最佳实践

10.1-代码组织结构

1.模块化设计:

  • 将应用程序划分为多个模块或包,例如 dao, service, controller 等。
  • 每个模块负责特定的功能,如数据访问、业务逻辑处理、用户交互等。

2.DAO 层设计:

  • DAO (Data Access Object) 层用于封装对数据库的操作。
  • 每个实体类都应该有一个对应的 DAO 接口和实现类。
  • DAO 接口定义了与数据库交互的方法,实现类则使用 MyBatis 来执行具体的 SQL 操作。

3.Service 层设计:

  • Service 层用于处理业务逻辑。
  • 服务层调用 DAO 层提供的方法,并进行必要的业务逻辑处理。
  • 通常情况下,服务层不直接操作数据库。

4.Controller 层设计:

  • Controller 层负责接收 HTTP 请求并调用服务层进行处理。
  • 控制器层还负责将处理结果返回给客户端。

5.资源分离:

  • 将 MyBatis 的映射文件(XML 文件)与 Java 代码分离。
  • 映射文件应该放在专门的目录下,如 src/main/resources/mapper。
  • 映射文件中定义 SQL 查询语句和结果映射规则。

6.配置文件管理:

  • 使用单独的配置文件来管理 MyBatis 的配置信息,如数据库连接信息、插件配置等。
  • 配置文件应放置在 src/main/resources 目录下。

7.实体类设计:

  • 设计实体类时应遵循 POJO (Plain Old Java Object) 原则。
  • 实体类应仅包含属性和基本的 getter/setter 方法。
  • 避免在实体类中添加复杂的业务逻辑。

10.2-异常处理

统一异常处理:

  • 定义一套统一的异常处理机制,确保所有异常都能被正确捕获和处理。
  • 可以创建自定义异常类来区分不同类型的错误。

异常层次结构:

  • 根据异常类型定义不同的异常类,例如 DataAccessException、BusinessException 等。
  • 通过继承 RuntimeException 或 Exception 来创建自定义异常类。

异常抛出:

  • 在 DAO 层抛出 DataAccessException 类型的异常,表示数据访问过程中出现的问题。
  • 在 Service 层抛出 BusinessException 类型的异常,表示业务逻辑处理中的问题。

异常捕获:

  • 在 Controller 层捕获异常,并根据异常类型返回合适的响应。
  • 使用全局异常处理器来处理未被捕获的异常。

异常日志记录:

  • 在捕获异常时记录详细的错误信息,包括堆栈跟踪。
  • 使用日志框架(如 Logback、Log4j 等)记录异常信息

10.3-测试策略

单元测试:

  • 编写针对 DAO 层和服务层的单元测试。
  • 使用 JUnit 或 TestNG 框架编写测试用例。
  • 对于 DAO 层,可以使用内存数据库(如 H2)来进行测试。

集成测试:

  • 编写针对整个系统或子系统的集成测试。
  • 使用真实的数据库环境来测试数据访问层和业务逻辑层之间的交互。
  • 可以使用 Spring Boot 的 @SpringBootTest 注解来启动完整的应用上下文进行测试。

端到端测试:

  • 对整个应用流程进行端到端的测试,确保各个组件之间能够正常协作。
  • 使用 Selenium 或 RestAssured 等工具进行前端和后端的交互测试。

性能测试:

  • 使用 JMeter 或 Gatling 等工具进行性能测试,确保应用在高并发下的稳定性和性能。
  • 测试数据库查询性能,优化 SQL 语句和索引。

代码覆盖率:

  • 使用 JaCoCo 或 Cobertura 等工具来检查测试代码的覆盖率。
  • 努力提高代码覆盖率,确保关键路径和边界条件都得到了测试。

十一,实战案例

完整的应用示例
假设我们需要构建一个简单的博客系统,其中包含文章(Article)和标签(Tag)两个实体。我们将实现以下功能:

  • 添加文章。
  • 获取文章列表。
  • 更新文章。
  • 删除文章。
  • 添加标签。
  • 获取标签列表。
  • 更新标签。
  • 删除标签。

步骤 1: 创建项目结构
项目结构:
src/main/java: 存放 Java 源代码。
src/main/resources: 存放配置文件和映射文件。
模块划分:
com.example: 包含所有源代码。
com.example.model: 实体类。
com.example.mapper: 映射接口。
com.example.service: 服务层接口和实现。
com.example.controller: 控制器层。
com.example.config: 配置类。

步骤 2: 创建实体类
Article.java:

 package com.example.model;public class Article {private Integer id;private String title;private String content;private Integer authorId;// Getters and setters}

Tag.java:

   package com.example.model;public class Tag {private Integer id;private String name;// Getters and setters}

步骤 3: 创建映射接口
ArticleMapper.java:

   package com.example.mapper;import com.example.model.Article;import org.apache.ibatis.annotations.*;import java.util.List;public interface ArticleMapper {@Select("SELECT * FROM articles WHERE id = #{id}")Article findById(Integer id);@Insert("INSERT INTO articles(title, content, author_id) VALUES(#{title}, #{content}, #{authorId})")@Options(useGeneratedKeys = true, keyProperty = "id")void add(Article article);@Update("UPDATE articles SET title = #{title}, content = #{content} WHERE id = #{id}")void update(Article article);@Delete("DELETE FROM articles WHERE id = #{id}")void deleteById(Integer id);@Select("SELECT * FROM articles")List<Article> findAll();}

TagMapper.java:

   package com.example.mapper;import com.example.model.Tag;import org.apache.ibatis.annotations.*;import java.util.List;public interface TagMapper {@Select("SELECT * FROM tags WHERE id = #{id}")Tag findById(Integer id);@Insert("INSERT INTO tags(name) VALUES(#{name})")@Options(useGeneratedKeys = true, keyProperty = "id")void add(Tag tag);@Update("UPDATE tags SET name = #{name} WHERE id = #{id}")void update(Tag tag);@Delete("DELETE FROM tags WHERE id = #{id}")void deleteById(Integer id);@Select("SELECT * FROM tags")List<Tag> findAll();}

步骤 4: 创建服务层
ArticleService.java:

   package com.example.service;import com.example.mapper.ArticleMapper;import com.example.model.Article;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;@Servicepublic class ArticleService {private final ArticleMapper articleMapper;@Autowiredpublic ArticleService(ArticleMapper articleMapper) {this.articleMapper = articleMapper;}public Article findById(Integer id) {return articleMapper.findById(id);}public void add(Article article) {articleMapper.add(article);}public void update(Article article) {articleMapper.update(article);}public void deleteById(Integer id) {articleMapper.deleteById(id);}public List<Article> findAll() {return articleMapper.findAll();}}

TagService.java:

   package com.example.service;import com.example.mapper.TagMapper;import com.example.model.Tag;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;@Servicepublic class TagService {private final TagMapper tagMapper;@Autowiredpublic TagService(TagMapper tagMapper) {this.tagMapper = tagMapper;}public Tag findById(Integer id) {return tagMapper.findById(id);}public void add(Tag tag) {tagMapper.add(tag);}public void update(Tag tag) {tagMapper.update(tag);}public void deleteById(Integer id) {tagMapper.deleteById(id);}public List<Tag> findAll() {return tagMapper.findAll();}}

步骤 5: 创建控制器层
ArticleController.java:

   package com.example.controller;import com.example.model.Article;import com.example.service.ArticleService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import java.util.List;@RestController@RequestMapping("/articles")public class ArticleController {private final ArticleService articleService;@Autowiredpublic ArticleController(ArticleService articleService) {this.articleService = articleService;}@GetMapping("/{id}")public Article findById(@PathVariable Integer id) {return articleService.findById(id);}@PostMappingpublic void add(@RequestBody Article article) {articleService.add(article);}@PutMapping("/{id}")public void update(@PathVariable Integer id, @RequestBody Article article) {article.setId(id);articleService.update(article);}@DeleteMapping("/{id}")public void deleteById(@PathVariable Integer id) {articleService.deleteById(id);}@GetMappingpublic List<Article> findAll() {return articleService.findAll();}}

TagController.java:

   package com.example.controller;import com.example.model.Tag;import com.example.service.TagService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import java.util.List;@RestController@RequestMapping("/tags")public class TagController {private final TagService tagService;@Autowiredpublic TagController(TagService tagService) {this.tagService = tagService;}@GetMapping("/{id}")public Tag findById(@PathVariable Integer id) {return tagService.findById(id);}@PostMappingpublic void add(@RequestBody Tag tag) {tagService.add(tag);}@PutMapping("/{id}")public void update(@PathVariable Integer id, @RequestBody Tag tag) {tag.setId(id);tagService.update(tag);}@DeleteMapping("/{id}")public void deleteById(@PathVariable Integer id) {tagService.deleteById(id);}@GetMappingpublic List<Tag> findAll() {return tagService.findAll();}}

步骤 6: 配置 MyBatis
application.properties:

   spring.datasource.url=jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTCspring.datasource.username=rootspring.datasource.password=rootspring.datasource.driver-class-name=com.mysql.cj.jdbc.Drivermybatis.type-aliases-package=com.example.modelmybatis.mapper-locations=classpath:mapper/*.xml

MyBatisConfig.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.Configuration;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import javax.sql.DataSource;@Configuration@MapperScan("com.example.mapper")public class MyBatisConfig {@Beanpublic SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSource);factoryBean.setTypeAliasesPackage("com.example.model");PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();factoryBean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));return factoryBean.getObject();}}

步骤 7: 创建映射文件
ArticleMapper.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.ArticleMapper"><select id="findById

十二,社区和扩展

12.1-MyBatis 生态系统

MyBatis 的生态系统包括一系列官方支持的工具和扩展,以及社区贡献的各种插件和库。这些工具和扩展可以极大地提高开发效率和应用性能。
MyBatis Generator:

  • 一个强大的代码生成工具,可以根据数据库表自动生成映射文件和实体类。
  • 支持多种数据库和多种输出模板。

MyBatis Plus:

  • 一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
  • 提供了通用 Mapper、通用 Service,支持 Lambda 形式的条件构造器等特性。

MyBatis Cache:

  • 提供了一种缓存机制,可以显著提高查询性能。
  • 支持二级缓存,可以跨多个映射文件共享缓存数据。

MyBatis Type Handlers:

  • 提供了类型处理器,可以方便地处理不同类型的数据转换。
  • 支持自定义类型处理器,以满足特殊的数据类型需求。

MyBatis Pagination:

  • 提供了分页插件,可以方便地实现分页查询。
  • 支持多种数据库方言,自动处理分页 SQL。

MyBatis Dynamic SQL:

  • 提供了动态 SQL 的支持,可以在运行时构建 SQL 语句。
  • 支持多种条件组合,可以构建复杂的查询语句。

12.2-第三方工具集成

MyBatis 可以与许多第三方工具集成,以提高开发效率和应用质量。
Spring Boot:

  • 提供了自动配置的支持,可以轻松地将 MyBatis 集成到 Spring Boot 项目中。
  • 支持 MyBatis 的配置文件和映射文件的自动扫描。

Lombok:

  • 一个 Java 库,可以减少实体类中的样板代码。
  • 支持自动生成 getter 和 setter 方法,以及其他常用的方法。

Swagger:

  • 一个 API 文档生成工具,可以自动生成 RESTful API 的文档。
  • 支持从控制器类中提取 API 信息,生成详细的文档。

Flyway:

  • 一个数据库迁移工具,可以方便地管理数据库版本。
  • 支持 SQL 脚本和基于 Java 的迁移脚本。

JUnit/TestNG:

  • 测试框架,用于编写单元测试和集成测试。
  • 支持模拟对象和数据库操作,便于测试 MyBatis 的映射逻辑。

Mockito:

  • 一个流行的 Java 模拟框架,可以用来模拟对象的行为。
  • 适用于编写单元测试,特别是对于 DAO 层的测试。

Spring Data:

  • 提供了一种简单的方式来访问数据库。
  • 支持 CRUD 操作和分页等功能,可以与 MyBatis 结合使用。

HikariCP:

  • 一个高性能的 JDBC 连接池。
  • 支持多种数据库,可以显著提高数据库访问性能。

Druid:

  • 一个数据库连接池监控工具,提供了详细的监控信息。
  • 支持 SQL 执行时间统计、SQL 执行日志等功能。

PgPool-II:

  • PostgreSQL 的连接池和负载均衡工具。
  • 可以提高数据库的可用性和性能。

12.3-社区资源和文档

MyBatis 拥有丰富的社区资源和文档,可以帮助开发者快速上手和解决问题。
官方文档:
mybatis – MyBatis 3 | Introductionicon-default.png?t=N7T8https://mybatis.org/mybatis-3/提供了详细的使用指南和 API 文档。
GitHub 仓库:
GitHub - mybatis/mybatis-3: MyBatis SQL mapper framework for JavaMyBatis SQL mapper framework for Java. Contribute to mybatis/mybatis-3 development by creating an account on GitHub.icon-default.png?t=N7T8https://github.com/mybatis/mybatis-3包含了源代码、示例项目和贡献指南。
Stack Overflow:
Newest 'mybatis' Questions - Stack Overflowicon-default.png?t=N7T8https://stackoverflow.com/questions/tagged/mybatis提供了大量的问题解答和技术讨论。
Google Groups:
groups.google.comicon-default.png?t=N7T8https://groups.google.com/forum/#!forum/mybatis-user一个活跃的社区论坛,可以提问和交流经验。
中文社区:
Spring中文网 (mybatis.cn)icon-default.png?t=N7T8https://www.mybatis.cn/提供了中文版的文档和教程。
博客和教程:
MYBATIS Tutorial (tutorialspoint.com)icon-default.png?t=N7T8https://www.tutorialspoint.com/mybatis/index.htm
Page not found - Java Code Geeksicon-default.png?t=N7T8https://examples.javacodegeeks.com/spring-boot-mybatis-example/各种博客和网站上的教程和示例。
视频教程:

哔哩哔哩 (゜-゜)つロ 干杯~-bilibiliicon-default.png?t=N7T8https://www.bilibili.com/Bilibili 上有很多关于 MyBatis 的视频教程,适合初学者入门学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/402675.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pikachu-XSS漏洞之cookie值获取、钓鱼结果和键盘记录实战记录

目录 Pikachu-XSS漏洞之cookie值获取、钓鱼结果和键盘记录实战记录 一、XSS&#xff08;get型&#xff09;之cookie值获取&#xff1a; 二、xss&#xff08;post型&#xff09;之cookie值获取 三、Xss之钓鱼攻击 四、XSS获取键盘记 Pikachu-XSS漏洞之cookie值获取、钓鱼结果…

坐牢第二十七天(聊天室)

基于UDP的网络聊天室 一.项目需求&#xff1a; 1.如果有用户登录&#xff0c;其他用户可以收到这个人的登录信息 2.如果有人发送信息&#xff0c;其他用户可以收到这个人的群聊信息 3.如果有人下线&#xff0c;其他用户可以收到这个人的下线信息 4.服务器可以发送系统信息…

算法工程师第四十天(647. 回文子串 516.最长回文子序列 动态规划总结篇 )

参考文献 代码随想录 一、回文子串 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 示例 1&#xff1a; 输入&#xff1a;s "abc"…

【stm32项目】多功能智能家居室内灯光控制系统设计与实现(完整工程资料源码)

多功能智能家居室内灯光控制系统设计与实现 目录&#xff1a; 目录&#xff1a; 前言&#xff1a; 一、项目背景与目标 二、国内外研究现状&#xff1a; 2.1 国内研究现状&#xff1a; 2.2 国外研究现状&#xff1a; 2.3 发展趋势 三、硬件电路设计 3.1 总体概述 3.2 硬件连接总…

图像压缩算法

8.1 JPEG压缩 (JPEG Compression) 介绍 JPEG&#xff08;Joint Photographic Experts Group&#xff09;压缩是最常用的有损图像压缩算法之一。它通过减少图像中的冗余数据来实现高效压缩&#xff0c;特别适用于自然图像。 原理 JPEG压缩的基本步骤包括颜色空间转换、离散余…

WPF篇(18)-DataGrid数据表格控件+ComboBox下拉框控件

DataGrid数据表格控件 DataGrid是一个可以多选的数据表格控件。所以&#xff0c;它继承一个支持多选的父类——MultiSelector。 public abstract class MultiSelector : Selector {protected MultiSelector();public IList SelectedItems { get; }protected bool CanSelectMu…

Python学习day16-类与对象

这里写目录标题 类示例 成员方法self关键字 类与对象构造方法其他类内置方法&#xff08;魔术方法&#xff09;_str_符号_Lt_符号le小于等于比较eq比较运算小结 类 在Python中&#xff0c;class&#xff08;类&#xff09;是一种用于创建对象的模板或蓝图。它封装了数据&#…

基于Django的停车场车辆出入管理系统,可识别车牌图片

研究背景 随着城市化进程的加快&#xff0c;车辆数量不断增加&#xff0c;停车场的管理成为一个日益重要的课题。传统的停车场管理系统依赖人工登记和监控&#xff0c;不仅效率低下&#xff0c;而且容易出现疏漏和错误&#xff0c;难以满足现代社会对停车场管理智能化、高效化…

STM32标准库学习笔记-3.外部中断

参考教程&#xff1a;【STM32入门教程-2023版 细致讲解 中文字幕】 中断 中断含义&#xff1a;在计算机执行主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序&…

2024 国内自闭症学校排名榜:突破边界,创造无限可能

在 2024 年&#xff0c;当家长们面对国内自闭症学校的排名榜时&#xff0c;心中或许充满了期待与困惑。然而&#xff0c;这些排名榜虽然能提供一定的参考&#xff0c;但绝不能成为选择学校的唯一依据。家长们更需要深入了解每所学校的真实情况&#xff0c;通过线下考察&#xf…

python及pycharm安装配置

PS&#xff1a;这篇是对于初学者的python以及pycharm配置教程&#xff0c;配置完成后可以直接看我的python学习笔记来进行python全套学习&#xff0c;现在已更新第一部分。 Python学习笔记&#xff08;一&#xff09;-CSDN博客 目录 一、python以及pycharm的安装配置 1.1 py…

Nuxt3:构建的时候报错Search string not found: “for (const existingRoot of buildInfoVersionMap.roots)

我们完成初步页面开发后&#xff0c;需要构建下项目生成我们需要的页面&#xff0c;在执行构建的时候报错&#xff1a; 找了很多资料&#xff0c;这个问题是由于 vue-tsc v1 版本引起&#xff0c;只需要将 vue-tsc 升级到v2 即可 我们在执行删除的时候&#xff0c;结果发现它…

【MySQL】数据库约束

系列文章目录 第一章 数据库基础 第二章 数据库基本操作 文章目录 系列文章目录前言约束关键字一览NOT NULLUNIQUEDEFAULTPRIMARY KEY自增主键 FOREIGN KEY总结 前言 在学习了数据库的增删改查操作之后&#xff0c;接下来就需要进阶的学习关键字来完善SQL语句的条件。学习数据…

数据结构----链表

一丶概念 链表又称单链表、链式存储结构&#xff0c;用于存储逻辑关系为“一对一”的数据。 和顺序表不同同&#xff0c;使用链表存储数据&#xff0c;不强制要求数据在内存中集中存储&#xff0c;各个元素可以分散存储在内存中。 二丶特点 特点&#xff1a;内存不连…

DolphinScheduler集群部署问题(趟坑)总结

目录 官方文档 官方项目地址 问题解决 官方文档 DolphinScheduler | 文档中心 (apache.org) 官方项目地址 部署及使用过程中的问题可以参见项目Issue:Issues apache/dolphinscheduler GitHub GitHub - apache/dolphinscheduler at 3.2.2-release 问题解决 1、JVM在运…

Simple RPC - 05 从零开始设计一个客户端(下)_ 依赖倒置和SPI

文章目录 Pre概述依赖倒置原则与解耦设计与实现1. 定义接口来隔离调用方与实现类2. 实现类DynamicStubFactory3. 调用方与实现类的解耦 依赖注入与SPI的解耦依赖注入SPI&#xff08;Service Provider Interface&#xff09; 总结 Pre Simple RPC - 01 框架原理及总体架构初探 …

网络编程:OSI协议,TCP/IP协议,IP地址,UDP编程

目录 国际网络通信协议标准&#xff1a; 1.OSI协议&#xff1a; 2.TCP/IP协议模型&#xff1a; 应用层 &#xff1a; 传输层&#xff1a; 网络层&#xff1a; IPV4协议 IP地址 IP地址的划分&#xff1a; 公有地址 私有地址 MA…

dotnet常用命令详解

命令预览 基础命令 new&#xff1a;创建项目 restore&#xff1a;恢复依赖 build&#xff1a;编译项目 publish&#xff1a;生成项目需要的文件准备发布项目 run&#xff1a;运行项目 test&#xff1a;测试项目 vstest&#xff1a;从指定的程序集中运行测试 pack&#…

升级阿里云linux服务器上的php版本

查看已安装的php软件包 [rootiZbp13pl2v34qj0thwq9aiZ ~]# rpm -qa|grep php php74-php-common-7.4.26-1.el7.remi.x86_64 oniguruma5php-6.9.7.1-1.el7.remi.x86_64 php74-php-gd-7.4.26-1.el7.remi.x86_64 php74-php-opcache-7.4.26-1.el7.remi.x86_64 php74-php-json-7.4.2…

记录|Git工具——下载GitHub项目

目录 前言一、Step 1. 下载Git二、Step2. 用Git Bash 下载到本地更新时间 前言 参考文章&#xff1a; 1、如何使用Git将Github项目拉到本地 2、git 安装、创建仓库、上传项目、克隆下载、常用命令 – 一篇文章总结&#xff08;适用github / gitee&#xff09; 3、Git的使用【入…