MyBatis工作原理、高级特性及整合到spring boot的步骤

2024-04-15 17:33:51 浏览数 (2)

MyBatis 是一个流行的开源 Java 持久层框架,主要用于简化与数据库之间的交互。它替代了传统的手工编写 JDBC 代码的方式,提供了方便的对象关系映射(ORM)功能,让开发者能更专注于业务逻辑和 SQL 的编写,而不是底层的数据库访问细节。

架构层次

MyBatis 分为三个主要层次:

1. 接口层(API Layer):

- 这一层主要对外暴露了 `SqlSession` 接口,它是应用程序与MyBatis框架交互的入口点。

- 应用程序通过 `SqlSession` 调用CRUD方法(如 `selectOne()`, `insert()`, `update()`, `delete()`)执行数据库操作。

- SqlSession通过工厂模式创建,工厂类是`SqlSessionFactory`,它负责读取MyBatis的配置信息并初始化环境。

2. 核心处理层(Core Processing Layer):

- 这一层包含了MyBatis的核心逻辑,包括:

- **配置解析**:读取和解析`mybatis-config.xml`和各个mapper的XML映射文件。

- **SQL解析**:将XML映射文件中的SQL语句和动态元素(如`<if>`、`<choose>`、`<foreach>`等)解析成可执行的SQL。

- **参数映射**:将Java对象属性值转换为SQL语句中的参数。

- **SQL执行**:通过JDBC驱动执行预编译的SQL语句。

- **结果集映射**:将查询结果按照映射配置转换回Java对象。

- **事务管理**:根据配置管理数据库事务。

3. 基础支撑层(Foundation Support Layer)

- 这一层包括一系列辅助组件,例如:

- **反射模块**:用于实例化Java对象、设置属性值。

- **类型转换模块**:处理不同数据库类型的转换,确保Java类型与数据库类型的一致性。

- **日志模块**:集成各种日志系统,输出MyBatis运行过程中的调试和跟踪信息。

- **缓存模块**:提供一级缓存(Session级别)和二级缓存(全局/应用级别),提高查询性能。

- **解析器模块**:解析XML配置文件和SQL映射文件。

- **资源加载模块**:负责加载配置文件和其他资源。

- **数据源模块**:管理数据库连接,实现连接池功能。

关键流程

MyBatis的主要工作流程如下:

1. 初始化:

- 通过`SqlSessionFactoryBuilder`利用`mybatis-config.xml`配置文件构建`SqlSessionFactory`。

- 创建`SqlSession`实例,这个过程中会初始化数据源、事务管理器等资源。

2. 执行SQL

- 应用程序调用`SqlSession`的方法来执行SQL。

- 方法调用经过一系列处理:

- 识别调用方法对应到哪个SQL映射语句。

- 如果SQL中有动态元素,则根据传入参数动态生成最终的SQL。

- 将Java对象的属性值映射为SQL参数。

- 从数据源获取数据库连接,并执行SQL。

- 获取结果集,并按照映射配置将结果映射回Java对象。

3. 清理资源:

- 当`SqlSession`不再需要时,需要手动或者通过AOP等方式关闭它,释放数据库连接,并提交或回滚事务。

MyBatis的设计理念在于简化开发者对JDBC的操作,同时保持高度的灵活性和可控性。

MyBatis 的高级特性主要包括以下几个方面:

1. 动态SQL

- MyBatis 提供了一组强大的动态SQL标签,允许根据条件动态生成SQL语句,避免硬编码SQL带来的问题。

xml

<select id="selectUsersIf" resultType="User">

SELECT * FROM user

<if test="username != null">

WHERE username = #{username}

</if>

</select>

<select id="selectUsersWhere" resultType="User">

SELECT * FROM user

<where>

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

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

</where>

</select>

<select id="selectUsersForeach" resultType="User">

SELECT * FROM user

<foreach item="item" index="index" collection="ids" open="WHERE id IN (" close=")" separator=",">

#{item}

</foreach>

</select>

2. 延迟加载(懒加载)

- 在一对多或多对多关联查询中,延迟加载是指在真正访问关联对象时才执行查询操作,而不是一开始就一次性加载所有关联数据。

java

// User 类

public class User {

private int id;

private String name;

// 延迟加载关联的 Account 列表

@LazyCollection(Lazy=true)

private List<Account> accounts;

// ... getter 和 setter ...

}

<!-- mapper.xml -->

<resultMap id="userResultMap" type="User">

<id property="id" column="user_id"/>

<result property="name" column="user_name"/>

<!-- 延迟加载关联表 -->

<collection property="accounts" javaType="ArrayList" ofType="Account"

select="com.example.mapper.AccountMapper.findByUserId" column="user_id" fetchType="lazy"/>

</resultMap>

3. 缓存

- MyBatis 提供了一级缓存(Session级别)和二级缓存(全局/应用级别),用于提高查询性能。

xml

<!-- 开启二级缓存并在全局配置文件中配置 -->

<settings>

<setting name="cacheEnabled" value="true"/>

</settings>

<!-- 在具体的mapper中声明使用二级缓存 -->

<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>

4. 插件机制

- MyBatis 允许自定义插件来拦截Executor、ParameterHandler、ResultSetHandler、StatementHandler这四个核心接口的方法,实现诸如分页、审计日志、性能监控等功能。

java

@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})

public class CustomPlugin implements Interceptor {

// 插件实现...

}

// 注册插件

<plugins>

<plugin interceptor="com.example.plugin.CustomPlugin"/>

</plugins>

5. 逆向工程

- MyBatis Generator可以根据数据库表结构自动生成对应的Mapper XML文件、DAO接口以及实体类。

xml

<!-- generatorConfig.xml -->

<generatorConfiguration>

<context id="DB2Tables" targetRuntime="MyBatis3">

<jdbcConnection driverClass="{username}" password="

<javaModelGenerator targetPackage="com.example.model" targetProject="src/main/java"/>

<sqlMapGenerator targetPackage="com.example.mapper" targetProject="src/main/resources"/>

<javaClientGenerator targetPackage="com.example.dao" targetProject="src/main/java" type="XMLMAPPER"/>

<table tableName="user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"/>

</context>

</generatorConfiguration>

Spring Boot整合MyBatis

1. 添加依赖

在你的Spring Boot项目中,需要添加MyBatis和相关数据库驱动的依赖。在`pom.xml`(Maven项目)或`build.gradle`(Gradle项目)中进行配置。以Maven为例:

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jdbc</artifactId>

</dependency>

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>2.2.0</version> <!-- 使用最新稳定版本 -->

</dependency>

<!-- 添加对应的数据库驱动,例如MySQL -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

</dependency>

</dependencies>

2. 配置数据源

在`application.properties`或`application.yml`中配置数据源信息,包括数据库URL、用户名、密码等:

properties

spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase

spring.datasource.username=root

spring.datasource.password=yourpassword

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

3. 创建实体类与Mapper接口

根据数据库表结构创建对应的Java实体类,并编写Mapper接口。例如,假设有一个`User`表,对应创建`User`类和`UserMapper`接口:

java

public class User {

private Long id;

private String username;

private String password;

// getters and setters...

}

public interface UserMapper {

User findById(Long id);

List<User> findAll();

void insert(User user);

void update(User user);

void deleteById(Long id);

}

4. 编写Mapper XML文件(可选)

虽然Spring Boot MyBatis支持全注解方式操作数据库,但你也可以选择使用XML文件来编写SQL语句。在resources目录下创建`mapper`目录,并为每个Mapper接口创建对应的XML文件,如`UserMapper.xml`:

xml

<mapper namespace="com.example.demo.mapper.UserMapper">

<select id="findById" resultType="com.example.demo.model.User">

SELECT * FROM user WHERE id = #{id}

</select>

<!-- 其他SQL语句... -->

</mapper>

5. 配置MyBatis

如果使用了Mapper XML文件,需要在配置类中指定其扫描路径。创建一个`@Configuration`类,如`MyBatisConfig`:

java

@Configuration

public class MyBatisConfig {

@Bean

public MapperScannerConfigurer mapperScannerConfigurer() {

MapperScannerConfigurer configurer = new MapperScannerConfigurer();

configurer.setBasePackage("com.example.demo.mapper"); // 替换为你实际的Mapper接口所在包名

return configurer;

}

}

6. 使用Mapper

现在可以在Service或Controller中通过@Autowired注入Mapper接口,然后调用其方法进行数据库操作:

java

@Service

public class UserService {

private final UserMapper userMapper;

@Autowired

public UserService(UserMapper userMapper) {

this.userMapper = userMapper;

}

public User getUserById(Long id) {

return userMapper.findById(id);

}

// 其他业务方法...

}

以上就是Spring Boot整合MyBatis的基本步骤。根据实际项目需求,可能还需要进行分页插件、日志插件等更高级的配置。

0 人点赞