2.2 参数处理


文档摘要

2.2 参数处理 MyBatis 映射器深入:2.2 参数处理详解 2.2.1 参数类型 MyBatis 提供了多种参数类型,以适应不同的业务场景。主要包括以下几种: 简单类型 (Primitive Types and Strings): 包括 , , , 等基本数据类型及其包装类。 POJO (Plain Old Java Object): 具有属性和 getter/setter 方法的 Java 对象。 Map: 使用键值对存储参数。 Collection 和 Array: 用于传递多个参数。 2.2.

2.2 参数处理

MyBatis 映射器深入:2.2 参数处理详解

2.2.1 参数类型

MyBatis 提供了多种参数类型,以适应不同的业务场景。主要包括以下几种:

  • 简单类型 (Primitive Types and Strings): 包括 int, long, String, Date 等基本数据类型及其包装类。

  • POJO (Plain Old Java Object): 具有属性和 getter/setter 方法的 Java 对象。

  • Map: 使用键值对存储参数。

  • Collection 和 Array: 用于传递多个参数。

2.2.2 参数传递方式

MyBatis 提供了两种主要的参数传递方式:

  • #{} (Parameter Expression): 用于占位符,MyBatis 会将参数值安全地替换到 SQL 语句中,防止 SQL 注入。

  • ${} (String Substitution): 用于字符串替换,MyBatis 会直接将参数值拼接到 SQL 语句中。应谨慎使用,因为它容易导致 SQL 注入。

2.2.2.1 #{} 的使用

#{} 是 MyBatis 中最常用的参数传递方式。它使用预编译的 PreparedStatement,能够有效地防止 SQL 注入,并且具有更好的性能。

示例:

// Mapper 接口 public interface UserMapper { User getUserById(int id); List<User> getUsersByUsername(String username); void insertUser(User user); } // XML 映射文件 <select id="getUserById" parameterType="int" resultType="User"> SELECT * FROM users WHERE id = #{id} </select> <select id="getUsersByUsername" parameterType="String" resultType="User"> SELECT * FROM users WHERE username LIKE #{username} </select> <insert id="insertUser" parameterType="User"> INSERT INTO users (username, email, password) VALUES (#{username}, #{email}, #{password}) </insert>

在上面的例子中,#{id}, #{username}, #{email}, #{password} 都会被 MyBatis 转换为 PreparedStatement 的占位符,并安全地替换为实际的参数值。

2.2.2.2 ${} 的使用

${} 用于字符串替换,它不会进行预编译,而是直接将参数值拼接到 SQL 语句中。因此,使用 ${} 时必须非常小心,以防止 SQL 注入。

示例:

// Mapper 接口 public interface UserMapper { List<User> getUsersByOrder(String orderBy); } // XML 映射文件 <select id="getUsersByOrder" parameterType="String" resultType="User"> SELECT * FROM users ORDER BY ${orderBy} </select>

在这个例子中,${orderBy} 会被替换为实际的排序字段。如果 orderBy 的值来自用户输入,并且没有经过严格的验证,就可能导致 SQL 注入。

最佳实践:

  • 尽量避免使用 ${}

  • 如果必须使用 ${},务必对参数进行严格的验证和过滤。

  • 只允许使用预定义的、安全的字符串值。

2.2.2.3 多参数传递

当需要传递多个参数时,MyBatis 提供了以下几种方式:

  • 使用 @Param 注解: 在 Mapper 接口的方法参数上使用 @Param 注解,为每个参数指定一个名称。

  • 使用 Map: 将多个参数放入一个 Map 中,然后将 Map 传递给 Mapper 方法。

  • 使用 POJO: 创建一个包含所有参数的 POJO,然后将 POJO 传递给 Mapper 方法。

示例:使用 @Param 注解

// Mapper 接口 public interface UserMapper { User getUser(@Param("id") int id, @Param("username") String username); } // XML 映射文件 <select id="getUser" resultType="User"> SELECT * FROM users WHERE id = #{id} AND username = #{username} </select>

示例:使用 Map

// Mapper 接口 public interface UserMapper { User getUser(Map<String, Object> params); } // XML 映射文件 <select id="getUser" parameterType="map" resultType="User"> SELECT * FROM users WHERE id = #{id} AND username = #{username} </select> // Java 代码 Map<String, Object> params = new HashMap<>(); params.put("id", 1); params.put("username", "test"); User user = userMapper.getUser(params);

示例:使用 POJO

// POJO public class UserQuery { private int id; private String username; // getter 和 setter 方法 } // Mapper 接口 public interface UserMapper { User getUser(UserQuery query); } // XML 映射文件 <select id="getUser" parameterType="UserQuery" resultType="User"> SELECT * FROM users WHERE id = #{id} AND username = #{username} </select> // Java 代码 UserQuery query = new UserQuery(); query.setId(1); query.setUsername("test"); User user = userMapper.getUser(query);

2.2.3 动态 SQL 中的参数使用

MyBatis 的动态 SQL 功能允许根据不同的参数值,动态地构建 SQL 语句。常用的动态 SQL 标签包括 <if>, <choose>, <where>, <set>, <foreach> 等。

示例:使用 <if> 标签

<select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM Blog WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> </select>

在这个例子中,只有当 title 参数不为 null 时,才会添加 AND title like #{title} 条件。

示例:使用 <choose>, <when>, <otherwise> 标签

<select id="findActiveBlogLike" 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>

这个例子根据 titleauthor.name 的值,选择不同的查询条件。

示例:使用 <where> 标签

<select id="findActiveBlogLike" resultType="Blog"> SELECT * FROM Blog <where> state = ‘ACTIVE’ <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>

<where> 标签会自动处理 SQL 语句中的 ANDOR 前缀。

示例:使用 <set> 标签

<update id="updateAuthorIfNecessary" parameterType="domain.Author"> UPDATE Author <set> <if test="username != null">username=#{username},</if> <if test="password != null">password=#{password},</if> <if test="email != null">email=#{email},</if> bio=#{bio} </set> WHERE id=#{id} </update>

<set> 标签会自动处理 SQL 语句中的 , 后缀。

示例:使用 <foreach> 标签

<select id="selectPostIn" resultType="domain.Post"> SELECT * FROM Post WHERE id in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>

<foreach> 标签用于循环遍历集合,并生成 SQL 语句中的 IN 子句。

2.2.4 参数处理流程图

以下是一个简化的参数处理流程图,使用 Mermaid 语法绘制:

2.2.5 代码实践

以下是一个完整的代码实践,演示了如何使用 MyBatis 进行参数处理:

1. 创建数据库表:

CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL );

2. 创建 User POJO:

public class User { private int id; private String username; private String email; private String password; // getter 和 setter 方法 }

3. 创建 UserMapper 接口:

public interface UserMapper { User getUserById(int id); List<User> getUsersByUsername(String username); void insertUser(User user); void updateUser(User user); List<User> getUsersBySearchCriteria(Map<String, Object> criteria); }

4. 创建 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.UserMapper"> <select id="getUserById" parameterType="int" resultType="User"> SELECT * FROM users WHERE id = #{id} </select> <select id="getUsersByUsername" parameterType="String" resultType="User"> SELECT * FROM users WHERE username LIKE #{username} </select> <insert id="insertUser" parameterType="User"> INSERT INTO users (username, email, password) VALUES (#{username}, #{email}, #{password}) </insert> <update id="updateUser" parameterType="User"> UPDATE users <set> <if test="username != null">username = #{username},</if> <if test="email != null">email = #{email},</if> <if test="password != null">password = #{password},</if> </set> WHERE id = #{id} </update> <select id="getUsersBySearchCriteria" parameterType="map" resultType="User"> SELECT * FROM users <where> <if test="username != null"> AND username LIKE #{username} </if> <if test="email != null"> AND email LIKE #{email} </if> </where> </select> </mapper>

**5. 创建 MyBatis 配置

文件 (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/your_database_name?serverTimezone=UTC"/> <property name="username" value="your_username"/> <property name="password" value="your_password"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/example/UserMapper.xml"/> </mappers> </configuration>

6. 编写 Java 代码进行测试:

import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; public class MyBatisExample { public static void main(String[] args) throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession session = sqlSessionFactory.openSession()) { UserMapper userMapper = session.getMapper(UserMapper.class); // 根据 ID 查询用户 User user = userMapper.getUserById(1); System.out.println("User with ID 1: " + user.getUsername()); // 根据用户名模糊查询用户 List<User> users = userMapper.getUsersByUsername("%test%"); System.out.println("Users with username like 'test': " + users.size()); // 插入新用户 User newUser = new User(); newUser.setUsername("new_user"); newUser.setEmail("new_user@example.com"); newUser.setPassword("password"); userMapper.insertUser(newUser); session.commit(); // 提交事务 System.out.println("Inserted new user with ID: " + newUser.getId()); // 更新用户信息 user.setEmail("updated_email@example.com"); userMapper.updateUser(user); session.commit(); System.out.println("Updated user with ID: " + user.getId()); // 使用 Map 进行查询 Map<String, Object> criteria = new HashMap<>(); criteria.put("username", "%test%"); criteria.put("email", "%example.com%"); List<User> searchResults = userMapper.getUsersBySearchCriteria(criteria); System.out.println("Users matching search criteria: " + searchResults.size()); } } }

2.2.6 总结

MyBatis 的参数处理机制提供了灵活和强大的功能,能够满足各种复杂的业务需求。理解和掌握不同类型的参数传递方式、动态 SQL 的使用、以及安全最佳实践,是编写高质量 MyBatis 代码的关键。在使用${} 进行参数替换时,务必谨慎,避免 SQL 注入的风险。通过合理地使用 @Param 注解、Map 或 POJO,可以简化多参数传递的代码。结合动态 SQL 标签,可以根据不同的参数值,动态地构建 SQL 语句,提高代码的灵活性和可维护性。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U