MyBatis XML 映射文件:`select`, `insert`, `update`, `delete` 标签详解

MyBatis XML 映射文件:select, insert, update, delete 标签详解

大家好,我是你们的码农老司机,今天咱们不飙车,聊聊 MyBatis 里面那些看起来人畜无害,实则暗藏玄机的 XML 标签:select, insert, update, delete。 别看它们只有短短几个字母,但它们可是 MyBatis 的灵魂,是连接 Java 代码和数据库的桥梁,是让你的代码飞起来的关键!

准备好了吗? 系好安全带,咱们这就出发!

什么是 MyBatis XML 映射文件?

首先,咱们得搞清楚 MyBatis XML 映射文件是啥玩意儿。 简单来说,它就是一个 XML 文件,里面定义了 SQL 语句,以及 Java 方法和 SQL 语句之间的映射关系。 想象一下,你的 Java 代码想从数据库里查点东西,或者往数据库里塞点数据,总不能直接把 SQL 语句写在 Java 代码里吧? 那样代码就变成了一锅粥,可读性极差,维护起来更是噩梦。

MyBatis 的 XML 映射文件就像一个翻译官,它把你的 Java 方法调用翻译成 SQL 语句,然后执行 SQL 语句,再把结果翻译成 Java 对象,最后返回给你的 Java 代码。 这样,你的 Java 代码就不用直接跟 SQL 语句打交道了,代码更加清晰,维护起来也更加方便。

select 标签:查询小能手

select 标签是 MyBatis 中最常用的标签之一,它负责从数据库中查询数据。 咱们先来看一个简单的例子:

<select id="getUserById" parameterType="int" resultType="com.example.User">
    SELECT id, name, age, email FROM user WHERE id = #{id}
</select>

这段 XML 代码定义了一个名为 getUserById 的 SQL 查询语句,它接受一个 int 类型的参数(用户的 ID),并返回一个 com.example.User 类型的对象。

  • id 属性: id 属性是这个 select 标签的唯一标识符,它必须是唯一的,用于在 Java 代码中引用这个 SQL 语句。 相当于给这个 SQL 语句起了个名字。
  • parameterType 属性: parameterType 属性指定了传递给 SQL 语句的参数类型。 在这个例子中,参数类型是 int,表示我们将会传递一个整数作为参数。
  • resultType 属性: resultType 属性指定了 SQL 语句返回结果的类型。 在这个例子中,结果类型是 com.example.User,表示 SQL 语句将会返回一个 User 类型的对象。 MyBatis 会自动将查询结果映射到 User 对象的属性中。
  • #{id} 这个是 MyBatis 的占位符,它会被替换成实际的参数值。 MyBatis 会自动处理 SQL 注入的问题,所以你不用担心安全问题。

使用 select 标签的 Java 代码:

SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    User user = sqlSession.selectOne("getUserById", 1); // 1 是用户的 ID
    System.out.println(user);
} finally {
    sqlSession.close();
}

这段 Java 代码首先获取一个 SqlSession 对象,然后调用 selectOne 方法执行 getUserById 查询语句,并将用户的 ID (1) 作为参数传递给 SQL 语句。 最后,selectOne 方法返回一个 User 对象,我们可以把它打印出来。

select 标签的其他属性:

  • resultMap 属性: 如果你的数据库字段名和 Java 对象的属性名不一致,或者你需要进行一些复杂的映射,可以使用 resultMap 属性来指定一个 resultMapresultMap 可以让你更灵活地控制结果的映射过程。
  • parameterMap 属性: parameterMap 属性已经不建议使用了,现在都使用 parameterType#{} 占位符来传递参数。
  • fetchSize 属性: fetchSize 属性可以指定每次从数据库中获取的数据行数。 这对于处理大型数据集非常有用,可以避免一次性加载所有数据导致内存溢出。
  • timeout 属性: timeout 属性可以指定 SQL 语句的执行超时时间。 如果 SQL 语句执行时间超过了这个时间,MyBatis 会抛出一个异常。
  • statementType 属性: statementType 属性可以指定 SQL 语句的类型。 默认值是 PREPARED,表示使用预编译的 SQL 语句。 还可以设置为 STATEMENTCALLABLE
  • resultSetType 属性: resultSetType 属性可以指定结果集的类型。 默认值是 FORWARD_ONLY,表示只能向前滚动结果集。 还可以设置为 SCROLL_SENSITIVESCROLL_INSENSITIVE
  • flushCache 属性: flushCache 属性可以指定是否刷新缓存。 默认值是 false,表示不刷新缓存。
  • useCache 属性: useCache 属性可以指定是否使用缓存。 默认值是 true,表示使用缓存。

使用 resultMap 的例子:

假设你的数据库字段名是 user_name,而 Java 对象的属性名是 name,那么你可以使用 resultMap 来进行映射:

<resultMap id="userResultMap" type="com.example.User">
    <id property="id" column="id"/>
    <result property="name" column="user_name"/>
    <result property="age" column="age"/>
    <result property="email" column="email"/>
</resultMap>

<select id="getUserById" parameterType="int" resultMap="userResultMap">
    SELECT id, user_name, age, email FROM user WHERE id = #{id}
</select>

在这个例子中,我们定义了一个名为 userResultMapresultMap,它指定了 user_name 字段映射到 name 属性。 然后,我们在 select 标签中使用 resultMap 属性来引用这个 resultMap

insert 标签:数据插入专家

insert 标签负责向数据库中插入数据。 咱们来看一个例子:

<insert id="insertUser" parameterType="com.example.User">
    INSERT INTO user (name, age, email) VALUES (#{name}, #{age}, #{email})
</insert>

这段 XML 代码定义了一个名为 insertUser 的 SQL 插入语句,它接受一个 com.example.User 类型的参数,并将用户的姓名、年龄和邮箱插入到 user 表中。

  • parameterType 属性: parameterType 属性指定了传递给 SQL 语句的参数类型。 在这个例子中,参数类型是 com.example.User,表示我们将会传递一个 User 类型的对象作为参数。
  • #{name}, #{age}, #{email} 这些是 MyBatis 的占位符,它们会被替换成 User 对象的 nameageemail 属性的值。

使用 insert 标签的 Java 代码:

SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    User user = new User();
    user.setName("张三");
    user.setAge(20);
    user.setEmail("[email protected]");
    sqlSession.insert("insertUser", user);
    sqlSession.commit(); // 提交事务
} finally {
    sqlSession.close();
}

这段 Java 代码首先创建一个 User 对象,并设置用户的姓名、年龄和邮箱。 然后,调用 insert 方法执行 insertUser 插入语句,并将 User 对象作为参数传递给 SQL 语句。 最后,必须调用 sqlSession.commit() 提交事务,才能将数据真正插入到数据库中。

insert 标签的其他属性:

  • useGeneratedKeys 属性: 如果你的数据库支持自动生成主键,可以使用 useGeneratedKeys 属性来告诉 MyBatis 使用数据库自动生成的主键。
  • keyProperty 属性: keyProperty 属性指定了 Java 对象中用于存储自动生成的主键的属性名。
  • keyColumn 属性: keyColumn 属性指定了数据库表中用于存储自动生成的主键的列名。

使用 useGeneratedKeys 的例子:

假设你的 user 表的 id 列是自动生成的,那么你可以这样使用 useGeneratedKeys

<insert id="insertUser" parameterType="com.example.User" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
    INSERT INTO user (name, age, email) VALUES (#{name}, #{age}, #{email})
</insert>

在这个例子中,我们设置了 useGeneratedKeys 属性为 truekeyProperty 属性为 idkeyColumn 属性为 id。 这样,MyBatis 会在执行完 insert 语句后,自动将数据库自动生成的主键值设置到 User 对象的 id 属性中。

update 标签:数据更新大师

update 标签负责更新数据库中的数据。 咱们来看一个例子:

<update id="updateUser" parameterType="com.example.User">
    UPDATE user SET name = #{name}, age = #{age}, email = #{email} WHERE id = #{id}
</update>

这段 XML 代码定义了一个名为 updateUser 的 SQL 更新语句,它接受一个 com.example.User 类型的参数,并将用户的姓名、年龄和邮箱更新到 user 表中,更新的条件是用户的 ID。

  • parameterType 属性: parameterType 属性指定了传递给 SQL 语句的参数类型。 在这个例子中,参数类型是 com.example.User,表示我们将会传递一个 User 类型的对象作为参数。
  • #{name}, #{age}, #{email}, #{id} 这些是 MyBatis 的占位符,它们会被替换成 User 对象的 nameageemailid 属性的值。

使用 update 标签的 Java 代码:

SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    User user = new User();
    user.setId(1); // 用户的 ID
    user.setName("李四");
    user.setAge(25);
    user.setEmail("[email protected]");
    sqlSession.update("updateUser", user);
    sqlSession.commit(); // 提交事务
} finally {
    sqlSession.close();
}

这段 Java 代码首先创建一个 User 对象,并设置用户的 ID、姓名、年龄和邮箱。 然后,调用 update 方法执行 updateUser 更新语句,并将 User 对象作为参数传递给 SQL 语句。 最后,必须调用 sqlSession.commit() 提交事务,才能将数据真正更新到数据库中。

delete 标签:数据删除终结者

delete 标签负责从数据库中删除数据。 咱们来看一个例子:

<delete id="deleteUserById" parameterType="int">
    DELETE FROM user WHERE id = #{id}
</delete>

这段 XML 代码定义了一个名为 deleteUserById 的 SQL 删除语句,它接受一个 int 类型的参数(用户的 ID),并从 user 表中删除指定 ID 的用户。

  • parameterType 属性: parameterType 属性指定了传递给 SQL 语句的参数类型。 在这个例子中,参数类型是 int,表示我们将会传递一个整数作为参数。
  • #{id} 这个是 MyBatis 的占位符,它会被替换成实际的参数值(用户的 ID)。

使用 delete 标签的 Java 代码:

SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    sqlSession.delete("deleteUserById", 1); // 1 是用户的 ID
    sqlSession.commit(); // 提交事务
} finally {
    sqlSession.close();
}

这段 Java 代码调用 delete 方法执行 deleteUserById 删除语句,并将用户的 ID (1) 作为参数传递给 SQL 语句。 最后,必须调用 sqlSession.commit() 提交事务,才能将数据真正从数据库中删除。

动态 SQL:让 SQL 语句灵活起来

有时候,你的 SQL 语句需要根据不同的条件动态生成。 例如,你可能需要根据用户的姓名、年龄和邮箱来查询用户,但你不知道用户会输入哪些条件。 这时候,你就需要使用 MyBatis 的动态 SQL 功能。

MyBatis 提供了以下几种动态 SQL 标签:

  • <if> 标签: if 标签用于判断条件是否成立,如果条件成立,则将 if 标签中的 SQL 片段添加到 SQL 语句中。
  • <choose> ( <when>, <otherwise> ) 标签: choose 标签类似于 Java 中的 switch 语句,它用于选择多个条件中的一个。
  • <where> 标签: where 标签用于添加 WHERE 子句,并且会自动处理 ANDOR 关键字。
  • <set> 标签: set 标签用于添加 SET 子句,并且会自动处理逗号。
  • <trim> 标签: trim 标签可以自定义前缀、后缀和删除的前缀和后缀。
  • <foreach> 标签: foreach 标签用于循环遍历集合,并生成 SQL 片段。

使用 <if> 标签的例子:

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

在这个例子中,我们使用了三个 <if> 标签来判断用户的姓名、年龄和邮箱是否为空。 如果姓名不为空,则添加 name LIKE #{name} 条件。 如果年龄不为空,则添加 AND age = #{age} 条件。 如果邮箱不为空,则添加 AND email LIKE #{email} 条件。 where 标签会自动处理 AND 关键字,所以你不用担心 SQL 语句出错。

使用 <foreach> 标签的例子:

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

在这个例子中,我们使用了 <foreach> 标签来循环遍历一个 ID 列表,并生成 id IN (1, 2, 3) 这样的 SQL 片段。 item 属性指定了当前循环的元素名,collection 属性指定了要遍历的集合,open 属性指定了 SQL 片段的前缀,separator 属性指定了元素之间的分隔符,close 属性指定了 SQL 片段的后缀。

总结:

MyBatis 的 XML 映射文件是 MyBatis 的核心,它定义了 SQL 语句以及 Java 方法和 SQL 语句之间的映射关系。 select, insert, update, delete 标签是 MyBatis 中最常用的标签,它们分别负责从数据库中查询数据、向数据库中插入数据、更新数据库中的数据和删除数据库中的数据。 动态 SQL 功能可以让你根据不同的条件动态生成 SQL 语句,让 SQL 语句更加灵活。

掌握了这些知识,你就可以轻松地使用 MyBatis 来操作数据库了。 希望这篇文章对你有所帮助,祝你编程愉快!

表格:MyBatis XML 映射文件标签属性总结

标签 常用属性 描述
select id 唯一标识符,用于在 Java 代码中引用这个 SQL 语句。
parameterType 传递给 SQL 语句的参数类型。
resultType SQL 语句返回结果的类型。
resultMap 用于指定一个 resultMap,可以更灵活地控制结果的映射过程。
insert id 唯一标识符,用于在 Java 代码中引用这个 SQL 语句。
parameterType 传递给 SQL 语句的参数类型。
useGeneratedKeys 是否使用数据库自动生成的主键。
keyProperty Java 对象中用于存储自动生成的主键的属性名。
keyColumn 数据库表中用于存储自动生成的主键的列名。
update id 唯一标识符,用于在 Java 代码中引用这个 SQL 语句。
parameterType 传递给 SQL 语句的参数类型。
delete id 唯一标识符,用于在 Java 代码中引用这个 SQL 语句。
parameterType 传递给 SQL 语句的参数类型。

再来个更加复杂的例子,整合动态 SQL 和 resultMap:

假设我们需要根据用户的姓名、年龄范围和邮箱模糊匹配来查询用户,并且将查询结果映射到 User 对象,但是 User 对象的 fullName 属性需要由数据库中的 firstNamelastName 字段拼接而成。

<resultMap id="userResultMap" type="com.example.User">
    <id property="id" column="id"/>
    <result property="firstName" column="first_name"/>
    <result property="lastName" column="last_name"/>
    <result property="fullName" column="first_name" select="getFullName"/>
    <result property="age" column="age"/>
    <result property="email" column="email"/>
</resultMap>

<select id="getFullName" parameterType="com.example.User" resultType="string">
    SELECT CONCAT(first_name, ' ', last_name) FROM user WHERE id = #{id}
</select>

<select id="findUsers" parameterType="map" resultMap="userResultMap">
    SELECT id, first_name, last_name, age, email FROM user
    <where>
        <if test="name != null and name != ''">
            AND (first_name LIKE #{name} OR last_name LIKE #{name})
        </if>
        <if test="minAge != null">
            AND age >= #{minAge}
        </if>
        <if test="maxAge != null">
            AND age <= #{maxAge}
        </if>
        <if test="email != null and email != ''">
            AND email LIKE #{email}
        </if>
    </where>
</select>

在这个例子中:

  1. 我们定义了一个 userResultMap,将数据库字段映射到 User 对象,并且使用 <result property="fullName" column="first_name" select="getFullName"/> 来指定 fullName 属性的值由 getFullName 查询语句返回。
  2. 我们定义了一个 getFullName 查询语句,用于拼接用户的 firstNamelastName
  3. 我们定义了一个 findUsers 查询语句,使用了动态 SQL 的 <if> 标签来根据不同的条件动态生成 SQL 语句。
  4. findUsers 接收一个 map 类型的参数,包含了查询条件,例如 nameminAgemaxAgeemail

对应的 Java 代码:

SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    Map<String, Object> params = new HashMap<>();
    params.put("name", "%张%"); // 模糊匹配姓名包含"张"的用户
    params.put("minAge", 20);  // 最小年龄为 20
    params.put("maxAge", 30);  // 最大年龄为 30
    params.put("email", "%@example.com%"); // 模糊匹配邮箱包含"@example.com"的用户

    List<User> users = sqlSession.selectList("findUsers", params);

    for (User user : users) {
        System.out.println(user); // 打印用户信息,包括拼接后的 fullName
    }
} finally {
    sqlSession.close();
}

这个例子展示了 MyBatis 强大的灵活性,你可以根据实际需求灵活地使用 resultMap 和动态 SQL 来构建复杂的查询。

希望这些例子能帮助你更好地理解 MyBatis 的 XML 映射文件! 记住,实践是检验真理的唯一标准,多多练习才能真正掌握这些技巧。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注