一、概述
MyBatis 是一个流行的 Java 持久层框架,它简化了数据库操作,让开发者专注于 SQL 本身。MyBatis 通过 XML 或注解来配置 SQL 语句,实现 Java 对象与 SQL 的映射,自动处理输入参数和结果集的映射。
核心功能:
SQL 映射:MyBatis 允许开发者通过 XML 文件或注解的方式将 SQL 语句与 Java 方法关联起来。
参数映射:可以自动将 Java 对象的属性映射到 SQL 语句中的参数。
结果映射:能够将 SQL 查询的结果集自动映射到 Java 对象。
特点:
易用性:相对于 JDBC,MyBatis 简化了数据库操作,开发者只需关注 SQL 本身。
灵活性:MyBatis 允许直接编写 SQL,易于优化和调试。
松耦合:MyBatis 不要求实现接口或继承类,减少了代码的侵入性。
动态 SQL:支持动态 SQL 的构建,可以根据不同的条件组合 SQL 语句。
二、配置文件
MyBatis 的主配置文件 mybatis-config.xml
是框架的核心配置文件,它控制着 MyBatis 的大部分行为。这个文件通常位于应用程序的类路径下,MyBatis 在启动时会加载它以配置其运行环境。以下是 mybatis-config.xml
文件中常见的几个重要部分:
-
properties(属性):用于外部化配置,比如数据库连接信息,可以通过加载外部的
.properties
文件来实现。 -
settings(全局配置参数):包含 MyBatis 的多种配置选项,如缓存设置、延迟加载开关、自动映射行为等。
-
typeAliases(类型别名):定义别名,简化实体类的完全限定名的使用,可以指定单个别名或通过包扫描自动应用别名。
-
typeHandlers(类型处理器):定义 Java 类型和 JDBC 类型之间的映射和转换逻辑。
-
objectFactory(对象工厂):用于创建对象的实例,可以通过自定义工厂类来改变 MyBatis 默认的对象创建方式。
-
plugins(插件):定义 MyBatis 插件,可以拦截方法调用,实现如分页、逻辑删除等功能。
-
environments(环境集合属性对象):配置数据库连接的环境,可以配置多个环境以适应不同的运行环境。
-
transactionManager(事务管理):指定事务管理的类型,如 JDBC 或托管给 Spring 管理。
-
dataSource(数据源):定义数据源的配置,可以是连接池或直接连接。
-
mappers(映射器):指定 SQL 映射文件的位置,可以是 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>
<!-- 属性配置 -->
<properties resource="db.properties" />
<!-- 设置 -->
<settings>
<setting name="cacheEnabled" value="true" />
<!-- 其他设置 -->
</settings>
<!-- 类型别名 -->
<typeAliases>
<typeAlias alias="user" type="org.mybatis.example.User" />
<!-- 包扫描别名 -->
<package name="org.mybatis.example" />
</typeAliases>
<!-- 类型处理器 -->
<typeHandlers>
<!-- 配置自定义类型处理器 -->
</typeHandlers>
<!-- 对象工厂 -->
<objectFactory type="org.mybatis.example.MyObjectFactory" />
<!-- 插件 -->
<plugins>
<!-- 配置插件 -->
</plugins>
<!-- 环境配置 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!-- 映射器 -->
<mappers>
<mapper resource="org/mybatis/example/UserMapper.xml" />
<!-- 其他映射器配置 -->
</mappers>
</configuration>
三、Mapper.xml映射文件
在 MyBatis 中,Mapper.xml
映射文件是一个关键组件,它包含了 SQL 映射语句和 Java 应用程序之间的桥梁。每个映射文件通常对应一个数据库表,包含了对该表进行操作的所有 SQL 语句。
1.命名空间(Namespace):
映射文件的 namespace
属性指定了映射文件中所有 SQL 语句的命名空间,通常是 Mapper 接口的完全限定名。
<mapper namespace="org.mybatis.example.UserMapper">
<!-- SQL 映射语句 -->
</mapper>
2.SQL 语句:
映射文件中定义了多种类型的 SQL 语句,如 select
、insert
、update
和 delete
。每个 SQL 语句都有一个 id
,这个 id
对应 Java 方法的名称。
<select id="queryAllEmp" resultType="Emp">
select *
from emp;
</select>
3.参数和结果类型:
parameterType:指定 SQL 语句的输入参数类型,可以是简单类型、Java POJO 或 Map 等。
resultType:指定 SQL 查询结果的输出类型,通常是 Java POJO 类型。
4.动态 SQL:
MyBatis 支持使用 <if>、<choose>、<when>、<otherwise>、<foreach> 等元素构建动态 SQL。
动态 SQL 是 MyBatis 的一个强大特性,它允许根据不同的条件动态地构建 SQL 语句。这种方式对于处理复杂的业务逻辑和多变的查询条件非常有用。以下是 MyBatis 支持的一些主要动态 SQL 元素及其用法:
(1)<if>
<if> 元素用于根据条件包含或排除 SQL 片段。它有一个 `test` 属性,该属性包含一个简单的布尔表达式。
<select id="selectUsers" resultType="User">
SELECT * FROM users
<if test="name != null">
WHERE name = #{name}
</if>
<if test="status != null">
AND status = #{status}
</if>
</select>
(2) `<choose>`, `<when>`, `<otherwise>`
`<choose>` 元素相当于一个条件选择语句,它包含多个 `<when>` 元素和一个可选的 `<otherwise>` 元素。每个 `<when>` 元素也有一个 `test` 属性。
<select id="selectUsers" resultType="User">
SELECT * FROM users
<where>
<choose>
<when test="name != null">
name = #{name}
</when>
<when test="status != null">
status = #{status}
</when>
<otherwise>
1 = 1
</otherwise>
</choose>
</where>
</select>
(3) `<trim>` 和 `<set>`
`<trim>` 元素用于去除 SQL 语句首尾的某些字符或标记。与 `<set>` 结合使用时,可以自动处理 `set` 子句中的逗号。
<update id="updateUser">
UPDATE users
<set>
<if test="name != null">name = #{name},</if>
<if test="status != null">status = #{status},</if>
</set>
WHERE id = #{id}
</update>
在这个例子中,`<trim>` 的 `suffixOverrides` 属性设置为 `","`,它会去除最后一个多余的逗号。
(4) `<foreach>`
`<foreach>` 元素用于对集合进行迭代,并动态地向 SQL 语句添加条件或值。它有 `collection`, `item`, `separator`, `open`, 和 `close` 属性。
<select id="selectUsersByIdList" resultType="User">
SELECT * FROM users
<where>
id IN
<foreach item="id" collection="idList" open="(" separator="," close=")">
#{id}
</foreach>
</where>
</select>
(5) `<bind>`
`<bind>` 元素允许将一个表达式的结果绑定到一个变量中,可以在 SQL 语句中使用这个变量。
<select id="selectUsers" resultType="User">
SELECT * FROM users
<where>
<bind name="startDate" value="'2024-01-01'"/>
<bind name="endDate" value="'2024-12-31'"/>
registrationDate BETWEEN #{startDate} AND #{endDate}
</where>
</select>
(6) SQL 片段引用 (`<include>`)
可以使用 `<include>` 元素来引用其他映射文件中定义的 SQL 片段,实现代码复用。
<select id="selectActiveUsers" resultType="User">
SELECT * FROM users
<include refid="activeUserCriteria"/>
</select>
<!-- 在其他映射文件中定义的 SQL 片段 -->
<sql id="activeUserCriteria">
WHERE status = 'ACTIVE'
</sql>
动态 SQL 使得 MyBatis 在处理复杂查询时更加灵活和强大。通过这些元素,开发者可以根据传递给方法的参数动态地构建出正确的 SQL 语句,而不必编写大量的条件语句。
5.高级映射:
使用 <resultMap> 可以定义复杂的结果映射,包括一对一、一对多的关联映射。
(1)association(关联映射)
用于一对一关联的对象映射。在 resultMap
中定义,可以将一个表中的数据映射到一个对象,同时将另一个表中与之关联的数据映射到该对象的属性中。
<resultMap id="userMap" type="User">
<id property="id" column="user_id" />
<result property="name" column="username" />
<association property="address" javaType="Address">
<id property="id" column="address_id" />
<result property="city" column="city" />
</association>
</resultMap>
(2)collection(集合映射)
用于一对多或多对多关联的集合映射。在 resultMap
中定义,可以将一个表中的数据映射到一个对象,同时将多个相关联的表中的数据映射到一个集合属性中。
<resultMap id="userWithOrdersMap" type="User">
<id property="id" column="user_id" />
<collection property="orders" ofType="Order">
<id property="id" column="order_id" />
<result property="orderDate" column="order_date" />
</collection>
</resultMap>
(3)discriminator(歧视词映射)
当一个表中有多个不同的类别,并且这些类别有共同的字段,但也有一些特有的字段时,可以使用歧视词映射来区分它们。通常与 association
或 collection
结合使用。
<resultMap id="productMap" type="Product">
<id property="id" column="product_id" />
<discriminator javaType="String" column="product_type">
<case value="BOOK" resultType="Book"/>
<case value="ELECTRONIC" resultType="Electronic"/>
</discriminator>
</resultMap>
(4)高级 resultType
使用 resultType
时,可以指定返回结果的类型,这可以是简单的 Java 类型、Java 实体类,也可以是 Map 类型。如果返回的是 Map 类型,还可以指定 key 属性。
List<Map<String, Object>> maps = sqlSession.selectList("findUsers");
(5)自动映射
MyBatis 允许在 settings
配置中开启自动映射功能,这样当列名和属性名一致时,MyBatis 会自动进行映射,无需显式定义 resultMap
。
<settings>
<setting name="autoMappingBehavior" value="FULL"/>
</settings>
(6)自定义类型处理器
当需要对特殊类型进行处理时,可以自定义类型处理器(TypeHandler
),在映射文件中指定使用这些处理器。
<typeHandlers>
<typeHandler handler="com.example.MyCustomTypeHandler"/>
</typeHandlers>
总结:
MyBatis 是一个高效的 Java 持久层框架,它通过 XML 或注解简化了 JDBC 的复杂操作,支持动态 SQL 和高级映射特性,如一对一、一对多关系映射。它以易用性、灵活性和松耦合著称,允许开发者编写强大且易于维护的 SQL 语句,同时提供了丰富的配置和扩展机制,适用于各种复杂的数据库操作场景。