1. MyBatis快速入门指南
作为Java生态中最受欢迎的持久层框架之一,MyBatis凭借其灵活的SQL映射能力和简洁的配置方式,已经成为企业级应用开发的标准配置。我在实际项目中接触MyBatis已有7年时间,今天就从最基础的配置开始,带大家快速掌握MyBatis的核心用法。
对于刚接触MyBatis的开发者来说,最需要明确的是它解决的核心问题:如何在Java对象和数据库记录之间建立映射关系,同时保留对SQL的完全控制权。与Hibernate等全自动ORM框架不同,MyBatis采用半自动化的方式,让开发者可以自由编写SQL,同时又免去了JDBC中繁琐的参数设置和结果集处理。
2. 环境准备与基础配置
2.1 项目依赖配置
以Maven项目为例,需要在pom.xml中添加以下核心依赖:
xml复制<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
如果使用MyBatis-Spring整合(推荐方式),还需要添加:
xml复制<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
注意:版本号请根据实际情况调整,建议使用Maven中央仓库中的最新稳定版
2.2 核心配置文件
MyBatis的主配置文件通常命名为mybatis-config.xml,放在resources目录下:
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.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
3. 核心组件详解
3.1 SqlSessionFactory构建
SqlSessionFactory是MyBatis的核心对象,每个数据库对应一个SqlSessionFactory实例:
java复制String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
实际项目中,我们通常会使用Spring来管理这个生命周期:
java复制@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setMapperLocations(
new PathMatchingResourcePatternResolver()
.getResources("classpath:mapper/*.xml"));
return sessionFactory.getObject();
}
3.2 Mapper接口与XML映射
MyBatis的Mapper有两种使用方式:XML配置和注解方式。对于复杂SQL,推荐使用XML配置:
UserMapper.java接口:
java复制public interface UserMapper {
User selectUserById(Long id);
List<User> selectAllUsers();
int insertUser(User user);
int updateUser(User user);
int deleteUser(Long id);
}
对应的UserMapper.xml:
xml复制<mapper namespace="com.example.mapper.UserMapper">
<resultMap id="userResultMap" type="User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="email" column="email"/>
</resultMap>
<select id="selectUserById" resultMap="userResultMap">
SELECT * FROM users WHERE id = #{id}
</select>
</mapper>
4. 动态SQL实践
MyBatis强大的动态SQL能力是其核心优势之一:
4.1 条件查询示例
xml复制<select id="findUsers" resultType="User">
SELECT * FROM users
<where>
<if test="username != null">
AND username = #{username}
</if>
<if test="email != null">
AND email = #{email}
</if>
</where>
LIMIT #{offset}, #{limit}
</select>
4.2 批量插入操作
xml复制<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO users(username, email) VALUES
<foreach collection="list" item="user" separator=",">
(#{user.username}, #{user.email})
</foreach>
</insert>
5. 高级特性与性能优化
5.1 一级缓存与二级缓存
MyBatis默认开启一级缓存(SqlSession级别),可以通过配置开启二级缓存(Mapper级别):
xml复制<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
注意:缓存使用不当会导致脏数据问题,在读写频繁的场景需谨慎使用
5.2 插件开发示例
实现一个简单的SQL执行时间统计插件:
java复制@Intercepts({
@Signature(type= StatementHandler.class,
method="query",
args={Statement.class, ResultHandler.class})
})
public class SqlCostPlugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
long start = System.currentTimeMillis();
Object result = invocation.proceed();
long end = System.currentTimeMillis();
System.out.println("SQL执行耗时:" + (end - start) + "ms");
return result;
}
}
在配置文件中注册插件:
xml复制<plugins>
<plugin interceptor="com.example.plugin.SqlCostPlugin"/>
</plugins>
6. 常见问题排查
6.1 "No MyBatis mapper was found"错误
这个问题通常出现在Spring Boot项目中,可能的原因包括:
- Mapper接口没有添加@Mapper注解
- 启动类缺少@MapperScan注解
- Mapper.xml文件没有放在正确位置
解决方案:
java复制@SpringBootApplication
@MapperScan("com.example.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
6.2 MyBatis日志不生效问题
确保在application.properties中正确配置:
properties复制logging.level.com.example.mapper=DEBUG
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
7. 最佳实践建议
- SQL管理:复杂的SQL建议写在XML中,简单的CRUD可以使用注解方式
- 结果映射:优先使用resultMap避免字段映射问题
- 事务控制:在Service层使用@Transactional注解
- 分页处理:推荐使用PageHelper等成熟分页插件
- 代码生成:利用MyBatis Generator自动生成基础CRUD代码
我在实际项目中发现,合理使用MyBatis的批量操作可以显著提升性能。比如在处理Excel导入时,相比单条插入,批量插入可以将性能提升10倍以上。但需要注意MySQL的max_allowed_packet参数限制,建议单批次不要超过1000条记录。
