MyBatis是一个优秀的Java持久层框架,它能够显著地简化数据库操作,并且提供了很多强大的功能,如动态SQL、缓存和延迟加载等。下面将根据前面提到的MyBatis知识点进行详细介绍。
- MyBatis的概述和特点
MyBatis是一个半自动化的ORM框架,它可以将Java对象映射到数据库表中。MyBatis的特点包括:
- 易于学习:MyBatis的学习曲线相对较平缓,而且它的语法和XML配置都非常直观。
- 灵活:MyBatis提供了很大的灵活性,通过XML配置实现的动态SQL和复杂映射关系,使得它可以胜任各种不同的数据库操作。
- 高效:MyBatis能够通过JDBC和数据库进行直接交互,避免了很多性能浪费。
- 易于测试:MyBatis提供了很好的单元测试支持,能够轻松地进行测试,保证代码质量。
- 优秀的社区支持:MyBatis有一个庞大和积极的开发者社区,提供了丰富的文档和教程,以及大量的高质量MyBatis插件和集成工具。
- MyBatis的架构和工作原理
MyBatis是一个基于数据映射的持久层框架,它由三部分组成:SQL Mapper、MyBatis核心和Sue-JDBC。
- SQL Mapper:负责将用户提交的SQL转换为JDBC能够执行的语句,以及对结果集进行映射。
- MyBatis核心:负责处理Mapper对应的配置文件,以及调度SQL Mapper,是整个框架的核心部分。
- Sue-JDBC:负责处理JDBC层面上的事情,包括管理连接、语句和结果集等。
MyBatis的工作流程一般如下:
-
在应用程序启动时,MyBatis会初始化MyBatis核心和连接池等资源,然后根据Mapper配置文件创建相应的Mapper代理对象。
-
应用程序调用Mapper接口方法时,MyBatis核心会根据Mapper接口方法的名称、参数类型和配置文件中的定义来寻找对应的SQL Mapper。
-
SQL Mapper会将用户传递的参数转换为JDBC能够执行的语句,并根据配置文件中的结果集映射规则将结果集转换为Java对象,并返回给MyBatis核心。
-
MyBatis核心将Java对象返回给应用程序。
-
MyBatis的配置
MyBatis的配置主要包括两个部分:数据源和MyBatis配置文件。
数据源
数据源是MyBatis连接到数据库的关键。MyBatis支持多种数据源,包括PooledDataSource和UnPooledDataSource。
PooledDataSource是一个带连接池的数据源,可以重用以前创建的连接,从而减轻数据库服务器的负担。配置PooledDataSource的示例代码如下:
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
UnPooledDataSource是一个不带连接池的数据源,每次请求都会创建一个新的连接。配置UnPooledDataSource的示例代码如下:
<dataSource type="UNPOOLED">
<property name="driver" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
MyBatis配置文件
MyBatis的配置文件是MyBatis框架的核心配置文件,其中包含了MyBatis的所有重要配置信息。一个完整的MyBatis配置文件包括以下几个部分:
- Properties配置
- Type Aliases配置
- Settings配置
- Type Handlers配置
- 拦截器配置
- Mappers配置
其中,Mappers配置是最重要的部分,它告诉MyBatis如何与数据库进行映射。以下是一个简单的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>
<!-- Properties配置 -->
<properties resource="db.properties">
<property name="username" value="sa" />
<property name="password" value="" />
</properties>
<!-- Type Aliases配置 -->
<typeAliases>
<typeAlias alias="User" type="com.example.User" />
</typeAliases>
<!-- Settings配置 -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true" />
<setting name="cacheEnabled" value="true" />
</settings>
<!-- Type Handlers配置 -->
...
<!-- 拦截器配置 -->
...
<!-- Mappers配置 -->
<mappers>
<mapper resource="com/example/UserMapper.xml" />
</mappers>
</configuration>
- MyBatis的映射文件
MyBatis的映射文件是指该框架中与SQL语句和Java对象之间的映射关系定义文件。其中一个关键性的配置是"ResultMap"配置,它需要配置在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.UserMapper">
<select id="selectUserById" parameterType="int" resultType="com.example.User">
select * from users where id = #{id}
</select>
<insert id=“addUser” parameterType="com.example.User">
insert into users(name, age) values(#{name}, #{age})
</insert>
</mapper>
在以上代码片段中,定义了一个"select"语句以及一个"insert"语句,其中"select"语句的"id"属性为"selectUserById",参数类型为"int",返回结果类型为"com.example.User";"insert"语句的"id"属性为"addUser",参数类型为"com.example.User"。
- 动态SQL语句
MyBatis提供了以下几种标签实现动态SQL语句:
- if:实现条件判断,根据结果生成不同的SQL语句。示例:
<select id="findBlog" resultMap="blog">
select * from blog
where 1=1
<if test="title != null">
and title like #{title}
</if>
<if test="author != null">
and author like #{author}
</if>
</select>
- choose、when、otherwise:实现多条件判断,根据结果生成不同的SQL语句。示例:
<select id="findBlog" resultMap="blog">
select * from blog
where 1=1
<choose>
<when test="title != null">
and title like #{title}
</when>
<when test="author != null">
and author like #{author}
</when>
<otherwise>
and status = 1
</otherwise>
</choose>
</select>
- foreach:实现循环操作,生成重复的SQL语句。示例:
<delete id="deleteBatch">
delete from user where id in
<foreach collection="ids" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</delete>
- 插件机制
MyBatis的插件机制可以通过自定义插件实现对SQL执行过程的拦截和修改。具体步骤如下:
- 编写自定义插件的拦截器,实现Interceptor接口,并在实现类上添加@Intercepts注解,指定要拦截的对象和方法。
- 在插件的XML配置文件中配置拦截器和要拦截的对象和方法。
- 将插件的XML配置文件交给MyBatis扫描。
示例:对SQL语句进行日志记录的插件
- 编写自定义插件拦截器LoggingInterceptor:
@Intercepts({@Signature(type=StatementHandler.class, method="update", args={Statement.class})})
public class LoggingInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
Object[] params = boundSql.getParameterObject();
String sql = boundSql.getSql();
System.out.println("SQL: " + sql);
System.out.println("params: " + Arrays.toString(params));
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
// do nothing
}
}
- 在插件的XML配置文件中配置拦截器和要拦截的对象和方法:
<plugins>
<plugin interceptor="com.test.LoggingInterceptor">
<property name="prop1" value="value1"></property>
</plugin>
</plugins>
- 二级缓存
MyBatis支持将查询结果缓存在进程外的缓存中,以减小数据库的压力。二级缓存需要在MyBatis的配置文件中进行配置。具体步骤如下:
-
在配置文件中开启二级缓存。
<settings> <setting name="cacheEnabled" value="true"/> </settings>
-
在映射文件中指定二级缓存。
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
- 根据不同的缓存实现方式进行相应的配置。
<!-- EHCache缓存实现方式 -->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
注意事项:
- 二级缓存需要根据实际情况进行配置,必须对缓存数据进行刷新以保证缓存数据的实时性。
- 不建议使用二级缓存缓存更新频繁的表或缓存大量数据的表。
- 缓存的实现方式对于应用的分布式部署也需要考虑相关问题。
8.延迟加载
MyBatis的延迟加载是指在需要查询关联表中的数据时才真正执行SQL语句,而不是在查询主表时就执行。延迟加载需要在MyBatis的配置文件中进行配置。具体步骤如下:
- 在配置文件中开启延迟加载。
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
- 在映射文件中指定延迟加载方式。
<association property="order" column="order_id" javaType="Order" select="selectOrderById" lazyLoad="true"/>
注意事项:
- 延迟加载需要注意关联表的数量,防止出现N+1查询的问题;需要考虑顺序查询的问题等。
- 不建议延迟加载大量数据或者频繁加载的数据。对于不同场景需要选择不同的延迟加载方式。
9.事务管理
MyBatis的事务管理机制使用的是JDBC的事务管理机制,也可以自定义实现事务管理器来适应不同的业务场景。具体步骤如下:
- 在配置文件中配置事务管理器。
<transactionManager type="JDBC"/>
- 使用事务注解@Transactional或编程式控制事务。
@Transactional
public void updateOrder(Order order) {
// 更新订单信息
...
}
注意事项:
- 在使用分布式事务时需要考虑多个数据库操作之间的协调问题。
- 在使用注解控制事务时需要适当地使用事务传播特性来管理事务。
10.整合其他框架
MyBatis可以和Spring、Spring Boot、Spring MVC等框架整合使用。整合方式如下:
- 在Spring等框架的配置文件中配置MyBatis相关的Bean。
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<bean id="userDao" class="com.test.dao.impl.UserDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
- 在Spring等框架的配置文件中配置事务管理器。
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
注意事项:
- 在整合MyBatis时需要注意版本兼容性问题。
- 在使用Spring等框架管理事务时需要适当配置事务传播特性来管理事务。
文章评论