Java——MyBatis从入门到精通:一站式学习指南_java mybatis
MyBatis从入门到精通:一站式学习指南
作为一款优秀的半自动ORM框架,MyBatis以其灵活的SQL控制和简洁的配置方式,成为Java后端开发中持久层框架的首选。本文将从基础概念到高级特性,全面讲解MyBatis的使用方法,包含实用代码示例和最佳实践。
一、MyBatis核心概念
1. 什么是MyBatis?
MyBatis是一款半自动ORM(对象关系映射)框架,本质是对JDBC的封装。与全自动ORM框架(如Hibernate)不同,MyBatis需要开发者手动编写SQL语句,但免除了JDBC中繁琐的连接管理、参数设置和结果集解析工作。
其核心优势在于:
- 支持自定义SQL,便于复杂查询和性能优化
- 强大的结果映射能力,自动完成数据库记录与Java对象的转换
- 轻量灵活,易于集成Spring等主流框架
- 适用于高并发、大数据量的互联网项目
2. 核心组件
MyBatis的工作流程依赖于以下核心组件:
- SqlSessionFactory:会话工厂,由SqlSessionFactoryBuilder根据配置文件创建,全局唯一
- SqlSession:数据库会话对象,用于执行SQL操作,生命周期为方法级
- Mapper接口:定义数据库操作方法的接口,无需实现类,MyBatis通过动态代理生成实现
- 映射文件:存储SQL语句和映射规则,与Mapper接口对应
二、环境搭建(Maven)
1. 引入依赖
在pom.xml
中添加MyBatis核心依赖和数据库驱动:
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.26</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency></dependencies>
2. 核心配置文件
创建mybatis-config.xml
(放在resources目录下),配置数据库连接和映射文件:
<!DOCTYPE configuration PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-config.dtd\"><configuration> <environments default=\"mysql\"> <environment id=\"mysql\"> <transactionManager type=\"JDBC\"/> <dataSource type=\"POOLED\"> <property name=\"driver\" value=\"com.mysql.cj.jdbc.Driver\"/> <property name=\"url\" value=\"jdbc:mysql://localhost:3306/mybatis_db?serverTimezone=UTC\"/> <property name=\"username\" value=\"root\"/> <property name=\"password\" value=\"root\"/> </dataSource> </environment> </environments> <mappers> <mapper resource=\"mapper/UserMapper.xml\"/> </mappers></configuration>
三、基本CRUD操作
1. 定义实体类
创建与数据库表对应的POJO类:
public class User { private Integer id; private String username; private String sex; private String address; // 省略getter、setter和toString方法}
2. Mapper接口与映射文件
(1)Mapper接口
public interface UserMapper { // 查询所有用户 List<User> findAll(); // 根据ID查询 User findById(Integer id); // 新增用户 void add(User user); // 更新用户 void update(User user); // 删除用户 void delete(Integer id);}
(2)映射文件(UserMapper.xml)
<!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=\"findAll\" resultType=\"com.example.pojo.User\"> select * from user </select> <select id=\"findById\" parameterType=\"int\" resultType=\"com.example.pojo.User\"> select * from user where id = #{id} </select> <insert id=\"add\" parameterType=\"com.example.pojo.User\"> insert into user(username, sex, address) values(#{username}, #{sex}, #{address}) </insert> <update id=\"update\" parameterType=\"com.example.pojo.User\"> update user set username = #{username}, sex = #{sex}, address = #{address} where id = #{id} </update> <delete id=\"delete\" parameterType=\"int\"> delete from user where id = #{id} </delete></mapper>
3. 测试代码
public class UserMapperTest { private SqlSession session; private UserMapper userMapper; @Before public void init() throws IOException { // 读取配置文件 InputStream is = Resources.getResourceAsStream(\"mybatis-config.xml\"); // 创建SqlSessionFactory SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); // 获取SqlSession session = factory.openSession(); // 获取Mapper代理对象 userMapper = session.getMapper(UserMapper.class); } @Test public void testFindAll() { List<User> users = userMapper.findAll(); users.forEach(System.out::println); } @Test public void testAdd() { User user = new User(); user.setUsername(\"张三\"); user.setSex(\"男\"); user.setAddress(\"北京\"); userMapper.add(user); session.commit(); // 手动提交事务 } @After public void destroy() { session.close(); }}
注意:MyBatis的事务默认手动提交,执行增删改操作后需调用
session.commit()
。
四、动态SQL
动态SQL是MyBatis的强大特性,可根据条件动态生成SQL片段,避免手动拼接SQL的繁琐和错误。
1.
标签:条件判断
<select id=\"findByCondition\" parameterType=\"com.example.pojo.User\" resultType=\"com.example.pojo.User\"> select * from user <where> <if test=\"username != null and username != \'\'\"> and username like #{username} </if> <if test=\"sex != null and sex != \'\'\"> and sex = #{sex} </if> </where></select>
标签会自动处理多余的
AND
,替代传统的where 1=1
写法
2.
标签:遍历集合
用于批量操作(如批量删除):
<delete id=\"deleteBatch\" parameterType=\"int\"> delete from user where id in <foreach collection=\"array\" open=\"(\" close=\")\" separator=\",\" item=\"id\"> #{id} </foreach></delete>
collection
:集合类型(数组用array
,List用list
)item
:遍历的元素名open/close
:SQL片段的开始/结束符separator
:元素间的分隔符
3.
标签:多条件分支
类似Java的switch-case
:
<select id=\"findByLevel\" parameterType=\"User\" resultType=\"User\"> select * from user <where> <choose> <when test=\"level == 1\"> and age <span class=\"token entity named-entity\" title=\"< 18 </when> <when test=\"level == 2\"> and age between 18 and 30 </when> <otherwise> and age \">> 30 </otherwise> </choose> </where></select>
五、缓存机制
MyBatis提供两级缓存,用于减少数据库交互,提高查询效率。
1. 一级缓存
- 作用域:SqlSession(会话级)
- 特性:默认开启,同一SqlSession内的相同查询会复用缓存
- 失效场景:执行增删改操作、调用
clearCache()
或commit()
、关闭SqlSession
@Testpublic void testL1Cache() { // 第一次查询(从数据库获取) User user1 = userMapper.findById(1); // 第二次查询(从一级缓存获取) User user2 = userMapper.findById(1); System.out.println(user1 == user2); // true}
2. 二级缓存
- 作用域:SqlSessionFactory(应用级)
- 特性:需手动开启,同一工厂创建的SqlSession共享缓存
- 要求:缓存的POJO需实现
Serializable
接口
开启步骤:
- 配置全局开关(mybatis-config.xml):
<settings> <setting name=\"cacheEnabled\" value=\"true\"/></settings>
- 在映射文件中声明缓存:
<mapper namespace=\"com.example.mapper.UserMapper\"> <cache size=\"1024\"/> </mapper>
- 实体类实现序列化:
public class User implements Serializable { // 字段和方法...}
六、关联查询
MyBatis支持一对一、一对多等关联查询,通过和
标签实现。
1. 一对一查询(如学生-班级)
<resultMap id=\"studentMap\" type=\"com.example.pojo.Student\"> <id property=\"id\" column=\"sid\"/> <result property=\"name\" column=\"sname\"/> <association property=\"clazz\" column=\"cid\" javaType=\"com.example.pojo.Clazz\"> <id property=\"id\" column=\"cid\"/> <result property=\"name\" column=\"cname\"/> </association></resultMap><select id=\"findStudentWithClazz\" resultMap=\"studentMap\"> select s.id sid, s.name sname, c.id cid, c.name cname from student s left join clazz c on s.cid = c.id</select>
2. 一对多查询(如班级-学生)
<resultMap id=\"clazzMap\" type=\"com.example.pojo.Clazz\"> <id property=\"id\" column=\"cid\"/> <result property=\"name\" column=\"cname\"/> <collection property=\"students\" column=\"cid\" ofType=\"com.example.pojo.Student\"> <id property=\"id\" column=\"sid\"/> <result property=\"name\" column=\"sname\"/> </collection></resultMap><select id=\"findClazzWithStudents\" resultMap=\"clazzMap\"> select c.id cid, c.name cname, s.id sid, s.name sname from clazz c left join student s on c.id = s.cid</select>
七、MyBatis Generator自动生成代码
MyBatis Generator(MBG)是官方代码生成器,可根据数据库表自动生成POJO、Mapper接口和映射文件,减少重复工作。
1. 配置MBG插件(pom.xml)
<build> <plugins> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.7</version> <configuration> <configurationFile>src/main/resources/generatorConfig.xml</configurationFile> <overwrite>true</overwrite> </configuration> </plugin> </plugins></build>
2. 编写配置文件(generatorConfig.xml)
<!DOCTYPE generatorConfiguration PUBLIC \"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN\" \"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd\"><generatorConfiguration> <classPathEntry location=\"F:/maven/repository/mysql/mysql-connector-java/8.0.26/mysql-connector-java-8.0.26.jar\"/> <context id=\"mysql\" targetRuntime=\"MyBatis3\"> <commentGenerator> <property name=\"suppressAllComments\" value=\"true\"/> </commentGenerator> <jdbcConnection driverClass=\"com.mysql.cj.jdbc.Driver\" connectionURL=\"jdbc:mysql://localhost:3306/mybatis_db\" userId=\"root\" password=\"root\"/> <javaModelGenerator targetPackage=\"com.example.pojo\" targetProject=\"src/main/java\"/> <sqlMapGenerator targetPackage=\"mapper\" targetProject=\"src/main/resources\"/> <javaClientGenerator type=\"XMLMAPPER\" targetPackage=\"com.example.mapper\" targetProject=\"src/main/java\"/> <table tableName=\"user\"/> </context></generatorConfiguration>
3. 运行生成命令
在Maven插件中执行mybatis-generator:generate
,自动生成以下文件:
User.java
:POJO类UserMapper.java
:Mapper接口UserMapper.xml
:映射文件UserExample.java
:复杂查询条件构建类
八、分页插件PageHelper
PageHelper是MyBatis常用的分页插件,可简化分页查询实现。
1. 引入依赖
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.3.0</version></dependency>
2. 配置插件(mybatis-config.xml)
<plugins> <plugin interceptor=\"com.github.pagehelper.PageInterceptor\"> <property name=\"helperDialect\" value=\"mysql\"/> </plugin></plugins>
3. 使用示例
@Testpublic void testPage() { // 设置分页参数(页码从1开始,每页3条) PageHelper.startPage(1, 3); // 执行查询 List<User> users = userMapper.findAll(); // 封装分页结果 PageInfo<User> pageInfo = new PageInfo<>(users); System.out.println(\"总条数:\" + pageInfo.getTotal()); System.out.println(\"总页数:\" + pageInfo.getPages()); System.out.println(\"当前页数据:\" + pageInfo.getList());}
总结
MyBatis以其灵活性和高效性,在Java持久层框架中占据重要地位。本文从环境搭建到高级特性,涵盖了MyBatis的核心用法,包括CRUD操作、动态SQL、缓存机制、关联查询等。掌握这些内容后,可轻松应对日常开发中的数据库操作需求。
建议在实际项目中根据场景选择XML配置或注解开发(XML更适合复杂SQL,注解更简洁),并合理使用缓存和分页插件优化性能。