MyBatis 的映射文件(通常以 .xml
结尾)定义了 SQL 查询、更新、插入和删除操作与 Java 对象之间的映射关系。以下是一些常用的标签及其属性:
根标签
mapper
: 这是映射文件的根标签,其属性如下:namespace
: 定义命名空间,通常与接口的全限定名匹配。
<?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.demo.mapper.UserMapper">
</mapper>
SQL 语句定义标签
-
select
: 定义查询语句,属性包括:id
: 唯一标识符,与接口中的方法名对应。parameterType
: 参数类型,可以是类的全限定名或别名。resultType
: 返回值类型,可以是类的全限定名或别名。resultMap
: 返回值映射,引用下面定义的resultMap
标签。flushCache
: 是否刷新缓存。useCache
: 是否使用二级缓存。timeout
: 设置查询超时时间。
-
insert
: 定义插入语句,属性包括:id
: 唯一标识符。parameterType
: 参数类型。keyProperty
: 主键对应的属性名。keyColumn
: 数据库中的主键列名。useGeneratedKeys
: 是否使用 JDBC 支持的自增主键。
-
update
: 定义更新语句,属性包括:id
: 唯一标识符。parameterType
: 参数类型。
-
delete
: 定义删除语句,属性包括:id
: 唯一标识符。parameterType
: 参数类型。
结果映射标签
resultMap
: 定义结果集和对象属性之间的映射关系,属性包括:id
: 唯一标识符。type
: 映射到的 Java 类的全限定名或别名。- 子标签包括:
id
:用于标识结果映射的唯一性,通常用于主键。result
:用于映射普通列到 Java 对象的属性。association
:用于映射复杂的类型,如一对一的关系。collection
:用于映射集合类型,如一对多的关系。constructor
:用于在实例化类时,将结果注入到构造方法中。discriminator
:用于根据结果值改变映射的行为。
<id property="id" column="user_id"/>
中的property="id"
指的是Java实体类中名为id
的属性,而column="user_id"
指的是数据库表中名为user_id
的列。这个映射告诉MyBatis,数据库表中的user_id
列应该被映射到Java实体类中的id
属性上。
<resultMap id="userMap" type="User">
<!-- 映射主键 -->
<id property="id" column="user_id"/>
<!-- 映射普通列 -->
<result property="username" column="username"/>
<result property="email" column="email"/>
<!-- 映射一对一的关系 -->
<association property="address" javaType="Address">
<id property="id" column="address_id"/>
<result property="street" column="street"/>
<result property="city" column="city"/>
<result property="zipcode" column="zipcode"/>
</association>
<!-- 映射一对多的关系 -->
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="title" column="title"/>
<result property="content" column="content"/>
</collection>
<!-- 使用构造方法注入结果 -->
<constructor>
<idArg column="user_id" javaType="int"/>
</constructor>
<!-- 根据结果值改变映射行为 -->
<discriminator javaType="int" column="type">
<case value="1" resultType="UserType1">
<!-- 映射类型1的特定属性 -->
</case>
<case value="2" resultType="UserType2">
<!-- 映射类型2的特定属性 -->
</case>
</discriminator>
</resultMap>
association
一对一映射
假设有一个User
类和一个Address
类,如下所示:
假设
users
表有一个字段(通常是外键)指向addresses
表的主键。这个字段在users
表中可能叫做address_id
,它用来关联每个用户与他们的地址。在Java实体类
User
中,这个关联是通过一个Address
类型的属性address
来表示的,而不是直接使用一个简单的address_id
字段。这个Address
属性代表了一个完整的地址对象,它包含了地址的所有详细信息。所以,当查询一个用户及其地址时,MyBatis会根据
address_id
字段在addresses
表中找到对应的地址记录,并将其封装成一个Address
对象,然后赋值给User
对象的address
属性。这样,我们就可以通过User
对象直接访问到与其关联的Address
对象,而无需手动处理这种关联关系。
public class User {
private Integer id;
private String username;
private String email;
private Address address; // 一对一关系
// 省略getter和setter方法
}
public class Address {
private Integer id;
private String street;
private String city;
private String zipcode;
// 省略getter和setter方法
}
在映射文件中使用<association>
来映射User
和Address
:
<association>标签中的两个属性property和javaType分别指的是实体类的属性名和实体类的属性类型
<mapper namespace="com.example.mapper.UserMapper">
<!-- 定义resultMap -->
<resultMap id="userMap" type="User">
<id property="id" column="user_id"/>
<result property="username" column="username"/>
<result property="email" column="email"/>
<!-- 映射一对一的关系 -->
<association property="address" javaType="Address">
<id property="id" column="address_id"/>
<result property="street" column="street"/>
<result property="city" column="city"/>
<result property="zipcode" column="zipcode"/>
</association>
</resultMap>
<!-- 使用resultMap的查询 这里的addresses是数据库表的表名-->
<select id="selectUserWithAddress" resultMap="userMap">
SELECT
u.id AS user_id,
u.username,
u.email,
a.id AS address_id,
a.street,
a.city,
a.zipcode
FROM
users u
LEFT JOIN
addresses a ON u.address_id = a.id
WHERE
u.id = #{userId}
</select>
</mapper>
collection一对多映射
constructor:
在实例化类时,将结果注入到构造方法中
discriminator
:用于根据结果值改变映射的行为
动态 SQL 标签
if
: 条件判断。
<select id="selectUsers" resultType="User">
SELECT * FROM users
WHERE 1=1
<if test="name != null">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</select>
choose (when, otherwise)
: 类似于 Java 中的 switch 语句。
<select id="findActiveBlogWithTitleLike" resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
where
: 动态生成 WHERE 子句。
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
set
: 用于动态生成 SET 子句。
<update id="updateAuthorIfNecessary">
UPDATE Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
WHERE id=#{id}
</update>
set
标签可以用于动态包含需要更新的列,并自动去除最后一个逗号。
foreach
: 用于迭代集合。
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
bind
: 创建变量并绑定到上下文中。
其他标签
sql
: 定义可重用的 SQL 代码片段。
<sql id="commonColumns">
id, username, email, created_at
</sql>
include
: 通过 refid 属性引用上面定义的<sql>
标签中的 SQL 代码片段。
<select id="selectUsers" resultType="User">
SELECT
<include refid="commonColumns"/>
FROM users
</select>
以上是 MyBatis 映射文件中常用的标签和属性,通过这些标签和属性,可以灵活地定义 SQL 操作和对象映射关系。