2.1 SQL 映射语句 MyBatis 映射器深入:2.1 SQL 映射语句详解 2.1.1 SQL 映射语句的定义 SQL 映射语句定义在 XML 映射文件中,通常以 , , , 这四个元素之一作为根元素。每个元素都对应着一种特定的 SQL 操作类型。 Graph TD 图示: 解释: Mapper File: 代表 XML 映射文件,是 SQL 映射语句的容器。 select, insert, update, delete: 代表四种基本的 SQL 操作类型,每个操作对应一个元素。 SQL Statement: 代表 SQL 语句本身,定义了具体的数据库操作逻辑。 2.1.
SQL 映射语句定义在 XML 映射文件中,通常以 <select>, <insert>, <update>, <delete> 这四个元素之一作为根元素。每个元素都对应着一种特定的 SQL 操作类型。
<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> <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>
Graph TD 图示:
解释:
Mapper File: 代表 XML 映射文件,是 SQL 映射语句的容器。
select, insert, update, delete: 代表四种基本的 SQL 操作类型,每个操作对应一个元素。
SQL Statement: 代表 SQL 语句本身,定义了具体的数据库操作逻辑。
每个 SQL 映射语句元素都包含一些重要的属性,用于配置其行为:
id (必需): 唯一标识符,用于在 Java 代码中引用该语句。 必须在namespace作用域内唯一。
parameterType (可选): 指定传递给 SQL 语句的参数类型。可以是 Java 基本类型、POJO (Plain Old Java Object) 或 Map。 如果参数类型是POJO或者Map,可以使用OGNL表达式访问属性。
parameterMap (不推荐使用): 与 parameterType 类似,但允许更复杂的参数映射。 现在一般使用parameterType配合OGNL表达式。
resultType (可选): 指定 SQL 语句返回结果的类型。可以是 Java 基本类型、POJO 或 Map。
resultMap (可选): 指定一个 resultMap 来映射结果集到 Java 对象。 用于处理复杂的映射关系,例如关联查询。
flushCache (可选): 设置为 true 时,语句执行后会清空本地和二级缓存。 默认为 false。
useCache (可选): 设置为 true 时,语句的结果会被缓存。 默认为 true 对于 select 语句,false 对于其他语句。
timeout (可选): 设置语句执行的超时时间,单位为秒。
statementType (可选): 指定语句的类型,可以是 STATEMENT (默认), PREPARED, 或 CALLABLE。 PREPARED 使用预编译语句,可以提高性能并防止 SQL 注入。
fetchSize (可选): 指定每次从数据库中获取的记录数。 用于处理大型结果集。
resultSetType (可选): 指定结果集的类型。 例如 FORWARD_ONLY, SCROLL_INSENSITIVE, SCROLL_SENSITIVE。
databaseId (可选): 指定该语句适用的数据库 ID。 用于支持多数据库环境。
除了这些属性,每个 SQL 映射语句还可以包含以下子元素:
<include>: 引用其他 SQL 片段,实现代码重用。
<selectKey>: 用于在插入数据后获取主键值。
<bind>: 创建一个变量,可以在 SQL 语句中使用。
<if>, <choose>, <when>, <otherwise>, <trim>, <where>, <set>, <foreach>: 动态 SQL 元素,用于根据条件生成 SQL 语句。
以下是一些 SQL 映射语句的代码实践示例,涵盖了不同的场景:
1. 查询用户:
<select id="getUserById" parameterType="int" resultType="com.example.model.User"> SELECT id, username, email FROM users WHERE id = #{id} </select>
Java 代码:
User user = sqlSession.selectOne("com.example.mapper.UserMapper.getUserById", 1);
解释:
id="getUserById":定义了语句的 ID,用于在 Java 代码中引用。
parameterType="int":指定参数类型为整数。
resultType="com.example.model.User":指定结果类型为 com.example.model.User 对象。
#{id}:占位符,用于将参数值替换到 SQL 语句中。
2. 插入用户:
<insert id="insertUser" parameterType="com.example.model.User"> INSERT INTO users (username, email) VALUES (#{username}, #{email}) <selectKey keyProperty="id" resultType="int" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey> </insert>
Java 代码:
User user = new User(); user.setUsername("testuser"); user.setEmail("test@example.com"); sqlSession.insert("com.example.mapper.UserMapper.insertUser", user); System.out.println("New user ID: " + user.getId());
解释:
id="insertUser":定义了语句的 ID。
parameterType="com.example.model.User":指定参数类型为 com.example.model.User 对象。
#{username} 和 #{email}:占位符,用于将 User 对象的 username 和 email 属性值替换到 SQL 语句中。
<selectKey>:用于在插入后获取自动生成的主键 id。 order="AFTER" 表示在插入之后执行。
3. 更新用户:
<update id="updateUser" parameterType="com.example.model.User"> UPDATE users <set> <if test="username != null">username = #{username},</if> <if test="email != null">email = #{email},</if> </set> WHERE id = #{id} </update>
Java 代码:
User user = new User(); user.setId(1); user.setUsername("newusername"); sqlSession.update("com.example.mapper.UserMapper.updateUser", user);
解释:
id="updateUser":定义了语句的 ID。
parameterType="com.example.model.User":指定参数类型为 com.example.model.User 对象。
<set>:动态 SQL 元素,用于自动添加 SET 关键字,并处理逗号。
<if>:动态 SQL 元素,用于根据条件添加更新字段。 只有当 username 和 email 属性不为 null 时,才会更新相应的字段。
4. 删除用户:
<delete id="deleteUser" parameterType="int"> DELETE FROM users WHERE id = #{id} </delete>
Java 代码:
sqlSession.delete("com.example.mapper.UserMapper.deleteUser", 1);
解释:
id="deleteUser":定义了语句的 ID。
parameterType="int":指定参数类型为整数。
#{id}:占位符,用于将参数值替换到 SQL 语句中。
5. 使用 <include> 元素:
<sql id="userColumns"> id, username, email </sql> <select id="getAllUsers" resultType="com.example.model.User"> SELECT <include refid="userColumns"/> FROM users </select>
解释:
<sql id="userColumns">: 定义了一个 SQL 片段,包含用户表的列名。
<include refid="userColumns"/>: 在 getAllUsers 语句中引用了 userColumns 片段,实现了代码重用。
6. 使用 <foreach> 元素:
<select id="getUsersByIds" 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>
Java 代码:
List<Integer> ids = Arrays.asList(1, 2, 3); List<User> users = sqlSession.selectList("com.example.mapper.UserMapper.getUsersByIds", ids);
解释:
parameterType="java.util.List":指定参数类型为 List。
<foreach>:动态 SQL 元素,用于遍历集合。
item="id":指定集合中的每个元素为 id。
collection="list":指定要遍历的集合为 list (List 类型必须是 list)。 如果参数是数组,则使用 array。
open="(":指定循环开始的字符为 (。
separator=",":指定循环元素之间的分隔符为 ,。
close=")":指定循环结束的字符为 )。
当数据库字段名和 Java 对象属性名不一致,或者需要处理关联查询时,可以使用 resultMap 来定义复杂的映射关系。
<resultMap id="userResultMap" type="com.example.model.User"> <id property="id" column="user_id"/> <result property="username" column="user_name"/> <result property="email" column="user_email"/> </resultMap> <select id="getUserByIdResultMap" parameterType="int" resultMap="userResultMap"> SELECT user_id, user_name, user_email FROM users WHERE user_id = #{id} </select>
解释:
<resultMap id="userResultMap" type="com.example.model.User">: 定义了一个 ID 为 userResultMap 的 resultMap,用于映射 com.example.model.User 对象。
<id property="id" column="user_id"/>: 将数据库字段 user_id 映射到 Java 对象的 id 属性。
<result property="username" column="user_name"/>: 将数据库字段 user_name 映射到 Java 对象的 username 属性。
<result property="email" column="user_email"/>: 将数据库字段 user_email 映射到 Java 对象的 email 属性。
<select id="getUserByIdResultMap" parameterType="int" resultMap="userResultMap">: 在 select 语句中使用 resultMap="userResultMap",指定使用该 resultMap 进行结果映射。
SQL 映射语句是 MyBatis 的核心组成部分,掌握其定义、元素、属性以及动态 SQL 的使用,能够有效地将 SQL 代码从 Java 代码中分离出来,提高代码的可维护性和可测试性。 通过本文的详细讲解和代码实践,希望读者能够深入理解 MyBatis 的 SQL 映射语句,并在实际项目中灵活运用。