架构层次
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的基本步骤。根据实际项目需求,可能还需要进行分页插件、日志插件等更高级的配置。