文集文档索引

Mybatis


  • 文集信息
  • 目录大纲
  • 最新文档
  • 知识宇宙

文集详情

文集导读

mybatis MyBatis 深度解析与实践 1. MyBatis 核心概念 SqlSessionFactory: MyBatis 的核心组件,负责创建 SqlSession。它基于 XML 配置文件或 Java 代码构建,是线程安全的。 SqlSession: 相当于 JDBC 的 Connection 对象,代表一个数据库会话。它提供了执行 SQL 命令、获取映射器实例、管理事务等方法。SqlSession 不是线程安全的,应在方法内部创建和销毁。 Mapper Interface: 定义了与数据库交互的方法,例如查询、插入、更新、删除等。Mapper 接口通过 XML 文件或注解与 SQL 语句进行绑定。 Mapper XML: 包含了 SQL 语句和参数映射,用于将 Mapper 接口的方法映射到具体的 SQL 操作。 Configuration: MyBatis 的配置对象,包含了数据库连接信息、映射器配置、插件配置等。 Executor: 负责执行 SQL 语句,管理事务,处理缓存。MyBatis 提供了三种 Executor 类型:SIMPLE, REUSE, BATCH。 StatementHandler: 负责与数据库进行实际的交互,例如执行 SQL 语句、设置参数、获取结果集。

mybatis

MyBatis 深度解析与实践

1. MyBatis 核心概念

  • SqlSessionFactory: MyBatis 的核心组件,负责创建 SqlSession。它基于 XML 配置文件或 Java 代码构建,是线程安全的。

  • SqlSession: 相当于 JDBC 的 Connection 对象,代表一个数据库会话。它提供了执行 SQL 命令、获取映射器实例、管理事务等方法。SqlSession 不是线程安全的,应在方法内部创建和销毁。

  • Mapper Interface: 定义了与数据库交互的方法,例如查询、插入、更新、删除等。Mapper 接口通过 XML 文件或注解与 SQL 语句进行绑定。

  • Mapper XML: 包含了 SQL 语句和参数映射,用于将 Mapper 接口的方法映射到具体的 SQL 操作。

  • Configuration: MyBatis 的配置对象,包含了数据库连接信息、映射器配置、插件配置等。

  • Executor: 负责执行 SQL 语句,管理事务,处理缓存。MyBatis 提供了三种 Executor 类型:SIMPLE, REUSE, BATCH。

  • StatementHandler: 负责与数据库进行实际的交互,例如执行 SQL 语句、设置参数、获取结果集。

  • ResultSetHandler: 负责将数据库返回的结果集映射成 Java 对象。

  • TypeHandler: 负责 Java 类型和 JDBC 类型之间的转换。

2. MyBatis 配置

MyBatis 的配置信息可以通过 XML 文件(mybatis-config.xml)或 Java 代码进行配置。XML 配置文件包含了数据源、事务管理器、映射器、插件等配置。

2.1 XML 配置示例 (mybatis-config.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.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis_db?serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="password"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/example/mapper/UserMapper.xml"/> </mappers> </configuration>
  • <environments>: 定义了多个环境,可以根据不同的环境使用不同的数据库连接。

  • <environment>: 定义了一个具体的环境,包含事务管理器和数据源。

  • <transactionManager>: 定义了事务管理器,可以选择 JDBCMANAGED

  • <dataSource>: 定义了数据源,可以选择 UNPOOLED, POOLEDJNDI

  • <mappers>: 指定了映射器文件的位置。

2.2 Java 代码配置

String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

这段代码通过读取 mybatis-config.xml 文件来构建 SqlSessionFactory

3. 映射器 (Mapper)

映射器是 MyBatis 的核心,它定义了 Java 接口和 SQL 语句之间的映射关系。

3.1 Mapper 接口

package com.example.mapper; import com.example.model.User; import java.util.List; public interface UserMapper { User getUserById(int id); List<User> getAllUsers(); void insertUser(User user); void updateUser(User user); void deleteUser(int id); }

3.2 Mapper XML (UserMapper.xml)

<?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.mapper.UserMapper"> <select id="getUserById" parameterType="int" resultType="com.example.model.User"> SELECT id, username, email FROM users WHERE id = #{id} </select> <select id="getAllUsers" resultType="com.example.model.User"> SELECT id, username, email FROM users </select> <insert id="insertUser" parameterType="com.example.model.User"> INSERT INTO users (username, email) VALUES (#{username}, #{email}) </insert> <update id="updateUser" parameterType="com.example.model.User"> UPDATE users SET username = #{username}, email = #{email} WHERE id = #{id} </update> <delete id="deleteUser" parameterType="int"> DELETE FROM users WHERE id = #{id} </delete> </mapper>
  • <mapper namespace>: 指定了映射器的命名空间,必须与 Mapper 接口的完全限定名一致。

  • <select>, <insert>, <update>, <delete>: 分别对应查询、插入、更新、删除操作。

  • id: 指定了 SQL 语句的唯一标识符,必须与 Mapper 接口的方法名一致。

  • parameterType: 指定了输入参数的类型。

  • resultType: 指定了返回结果的类型。

  • #{}: 用于引用参数,MyBatis 会自动处理参数类型转换。

3.3 使用 Mapper

SqlSession sqlSession = sqlSessionFactory.openSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.getUserById(1); System.out.println(user); List<User> users = userMapper.getAllUsers(); users.forEach(System.out::println); User newUser = new User(); newUser.setUsername("testUser"); newUser.setEmail("test@example.com"); userMapper.insertUser(newUser); sqlSession.commit(); // 提交事务 user.setUsername("updatedUser"); userMapper.updateUser(user); sqlSession.commit(); userMapper.deleteUser(2); sqlSession.commit(); } finally { sqlSession.close(); }

4. 动态 SQL

MyBatis 提供了强大的动态 SQL 功能,可以根据不同的条件生成不同的 SQL 语句。

4.1 <if> 标签

<select id="findUsers" parameterType="com.example.model.User" resultType="com.example.model.User"> SELECT id, username, email FROM users <where> <if test="username != null and username != ''"> username LIKE #{username} </if> <if test="email != null and email != ''"> AND email LIKE #{email} </if> </where> </select>

<if> 标签用于判断条件是否成立,如果成立则拼接 SQL 片段。<where>标签会自动处理第一个条件前的 ANDOR 关键字。

4.2 <choose>, <when>, <otherwise> 标签

<select id="findUsersChoose" parameterType="com.example.model.User" resultType="com.example.model.User"> SELECT id, username, email FROM users <where> <choose> <when test="username != null and username != ''"> username LIKE #{username} </when> <when test="email != null and email != ''"> email LIKE #{email} </when> <otherwise> 1=1 </otherwise> </choose> </where> </select>

<choose> 标签类似于 Java 中的 switch 语句,<when> 标签对应 case<otherwise> 标签对应 default

4.3 <foreach> 标签

<select id="findUsersByIds" parameterType="java.util.List" resultType="com.example.model.User"> SELECT id, username, email FROM users WHERE id IN <foreach item="id" collection="list" open="(" separator="," close=")"> #{id} </foreach> </select>

<foreach> 标签用于循环遍历集合,item 指定当前循环的元素,collection 指定要遍历的集合,open 指定循环开始的字符串,separator 指定元素之间的分隔符,close 指定循环结束的字符串。

4.4 <sql> 标签

<sql id="userColumns"> id, username, email </sql> <select id="getAllUsers" resultType="com.example.model.User"> SELECT <include refid="userColumns"/> FROM users </select>

<sql> 标签用于定义 SQL 片段,<include> 标签用于引用 SQL 片段,可以提高代码的重用性。

5. 关联查询

MyBatis 支持一对一、一对多、多对一、多对多的关联查询。

5.1 一对一关联

假设一个 User 对应一个 Address

// User 类 public class User { private int id; private String username; private String email; private Address address; // Address 对象 // 省略 getter 和 setter } // Address 类 public class Address { private int id; private String street; private String city; // 省略 getter 和 setter }
<!-- UserMapper.xml --> <resultMap id="UserResultMap" type="com.example.model.User"> <id property="id" column="user_id"/> <result property="username" column="username"/> <result property="email" column="email"/> <association property="address" javaType="com.example.model.Address"> <id property="id" column="address_id"/> <result property="street" column="street"/> <result property="city" column="city"/> </association> </resultMap> <select id="getUserWithAddress" parameterType="int" resultMap="UserResultMap"> SELECT u.id AS user_id, u.username, u.email, a.id AS address_id, a.street, a.city FROM users u LEFT JOIN addresses a ON u.address_id = a.id WHERE u.id = #{id} </select>
  • <resultMap> 用于定义结果映射,可以将数据库字段映射到 Java 对象的属性。

  • <association> 用于定义一对一关联,property 指定 Java 对象的属性名,javaType 指定 Java 对象的类型。

5.2 一对多关联

假设一个 User 对应多个 Order

// User 类 public class User { private int id; private String username; private String email; private List<Order> orders; // Order 列表 // 省略 getter 和 setter } // Order 类 public class Order { private int id; private String orderNumber; // 省略 getter 和 setter }
<!-- UserMapper.xml --> <resultMap id="UserResultMapWithOrders" type="com.example.model.User"> <id property="id" column="user_id"/> <result property="username" column="username"/> <result property="email" column="email"/> <collection property="orders" ofType="com.example.model.Order"> <id property="id" column="order_id"/> <result property="orderNumber" column="order_number"/> </collection> </resultMap> <select id="getUserWithOrders" parameterType="int" resultMap="UserResultMapWithOrders"> SELECT u.id AS user_id, u.username, u.email, o.id AS order_id, o.order_number FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE u.id = #{id} </select>
  • <collection> 用于定义一对多关联,property 指定 Java 对象的属性名,ofType 指定 Java 对象的类型。

6. 缓存

MyBatis 提供了两级缓存:一级缓存(SqlSession 级别)和二级缓存(SqlSessionFactory 级别)。

  • 一级缓存: 默认开启,SqlSession 级别,在同一个 SqlSession 中,执行相同的查询语句,MyBatis 会从缓存中获取结果,避免重复查询数据库。

  • 二级缓存: 默认关闭,SqlSessionFactory 级别,多个 SqlSession 可以共享缓存数据。需要手动配置才能开启。

6.1 开启二级缓存

  1. mybatis-config.xml 中开启二级缓存:
<settings> <setting name="cacheEnabled" value="true"/> </settings>
  1. 在 Mapper XML 中配置 <cache> 标签:
<mapper namespace="com.example.mapper.UserMapper"> <cache/> <!-- ... --> </mapper>

7. 插件 (Plugins)

MyBatis 允许通过插件来拦截特定的方法调用,例如 Executor, StatementHandler, ParameterHandler, ResultSetHandler

7.1 自定义插件示例

package com.example.plugin; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.plugin.*; import java.sql.Connection; import java.util.Properties; @Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})}) public class MyPlugin implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); // 在执行 SQL 语句之前进行拦截 System.out.println("SQL 拦截器执行..."); return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { // 可以获取配置文件中的属性 String prop1 = properties.getProperty("prop1"); System.out.println("prop1 = " + prop1); } }
  • @Intercepts 注解用于指定要拦截的方法。

  • @Signature 注解用于指定要拦截的接口、方法名和参数类型。

  • intercept() 方法是插件的核心,可以在方法调用前后进行拦截处理。

  • plugin() 方法用于将插件应用到目标对象。

  • setProperties() 方法用于设置插件的属性。

7.2 配置插件

<!-- mybatis-config.xml --> <plugins> <plugin interceptor="com.example.plugin.MyPlugin"> <property name="prop1" value="value1"/> </plugin> </plugins>

8. MyBatis Generator

MyBatis Generator (MBG) 是一个代码生成工具,可以根据数据库表结构自动生成 Mapper 接口、Mapper XML 文件和 POJO 类,可以大大提高开发效率。

9. 总结

MyBatis 是一款功能强大的持久层框架,它提供了灵活的 SQL 映射、动态 SQL、关联查询、缓存、插件等功能,可以帮助开发者更好地管理数据库交互。 通过深入理解 MyBatis 的核心概念和配置,并结合实际代码示例,可以更好地运用 MyBatis 来构建高效、可维护的应用程序。

Graph TD 图

这个 Mermaid 图展示了 MyBatis 的主要组件以及它们之间的关系。

目录大纲

    最新文档

    知识宇宙

    正在加载知识图谱...


    转发