MyBatis 参数处理详解
在 MyBatis 中,参数处理是非常重要的部分,它支持灵活的参数传递方式,以实现与数据库的交互。MyBatis 提供了多种方式来传递参数,包括单个参数、多参数、Java 对象和集合等,这些参数通过 SQL 语句中的占位符动态绑定到 SQL 中。
一、MyBatis 单个参数处理
MyBatis 支持将单个参数传递给 SQL 语句,通常通过 #{}
或 ${}
来绑定参数。
1. #{}
与 ${}
的区别
-
#{}
占位符:这是 MyBatis 的标准参数占位符,它会在 SQL 语句执行时将参数安全地绑定到 PreparedStatement 中,防止 SQL 注入。sqlSELECT * FROM users WHERE id = #{id}
-
${}
占位符:它会直接将参数替换到 SQL 语句中,不会进行类型转换和 SQL 注入检查。通常用于动态表名或列名的拼接。sqlSELECT * FROM ${tableName}
2. 单个参数示例
在 Mapper 接口中传递单个参数时,可以直接使用基本数据类型或包装类。
java
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User selectUserById(int id);
}
此时,MyBatis 会自动将参数 id
绑定到 SQL 语句中的 #{id}
占位符上,并执行查询。
3. 动态 SQL 示例
使用 ${}
动态拼接表名或列名:
java
@Select("SELECT * FROM ${tableName} WHERE id = #{id}")
List<User> selectFromTable(@Param("tableName") String tableName, @Param("id") int id);
在此示例中,表名会动态拼接到 SQL 语句中,而 #{id}
则通过 PreparedStatement 绑定参数,保证 SQL 安全性。
二、MyBatis 多个参数处理
MyBatis 支持多个参数的传递。在处理多个参数时,MyBatis 会将参数封装为 param1
, param2
, param3
等形式,也可以使用 @Param
注解为每个参数指定名称,增强可读性。
1. 多个参数的自动映射
当传递多个参数时,MyBatis 默认按 param1
, param2
, param3
等名称来映射这些参数。
java
public interface UserMapper {
@Select("SELECT * FROM users WHERE name = #{param1} AND age = #{param2}")
List<User> selectUsersByNameAndAge(String name, int age);
}
在这种情况下,param1
对应第一个参数 name
,param2
对应第二个参数 age
。
2. 使用 @Param
注解传递多个参数
为了更清晰地传递多个参数,MyBatis 提供了 @Param
注解,允许开发者自定义参数名。
java
public interface UserMapper {
@Select("SELECT * FROM users WHERE name = #{name} AND age = #{age}")
List<User> selectUsersByNameAndAge(@Param("name") String name, @Param("age") int age);
}
使用 @Param
后,name
和 age
会被绑定到 SQL 语句中的 #{name}
和 #{age}
占位符上。
三、MyBatis 对象参数处理
MyBatis 支持将 Java 对象作为参数传递到 SQL 语句中。在这种情况下,MyBatis 会自动将对象的属性映射为 SQL 语句中的参数。
1. 传递单个 Java 对象
当我们将一个 Java 对象作为参数传递时,MyBatis 会自动根据对象的属性名匹配 SQL 语句中的占位符。
java
public class User {
private int id;
private String name;
private int age;
// getters and setters
}
public interface UserMapper {
@Insert("INSERT INTO users (id, name, age) VALUES (#{id}, #{name}, #{age})")
int insertUser(User user);
}
在这个例子中,#{id}
, #{name}
, #{age}
分别对应传入的 User
对象的属性。
2. 传递嵌套对象
如果 Java 对象中包含了嵌套对象,MyBatis 也支持通过嵌套属性进行参数映射。
java
public class Address {
private String city;
private String state;
// getters and setters
}
public class User {
private int id;
private String name;
private Address address;
// getters and setters
}
public interface UserMapper {
@Select("SELECT * FROM users WHERE city = #{address.city} AND state = #{address.state}")
List<User> selectUsersByAddress(User user);
}
在这个示例中,#{address.city}
和 #{address.state}
分别映射 User
对象中的 Address
对象的属性。
四、MyBatis 集合参数处理
MyBatis 支持传递集合类型(如 List
、Map
等)作为 SQL 语句的参数,常用于 IN
查询或批量插入操作。
1. List 参数
MyBatis 可以直接传递 List
类型的参数,通常用于 IN
查询中。
java
@Select("SELECT * FROM users WHERE id IN (#{ids})")
List<User> selectUsersByIds(@Param("ids") List<Integer> ids);
在 XML 中,使用 foreach
标签可以灵活处理 List
参数。
xml
<select id="selectUsersByIds" resultType="User">
SELECT * FROM users WHERE id IN
<foreach item="id" collection="list" open="(" separator="," close=")">
#{id}
</foreach>
</select>
2. Map 参数
MyBatis 也可以将 Map
作为参数传递,常用于动态 SQL 查询。
java
public interface UserMapper {
@Select("SELECT * FROM users WHERE name = #{name} AND age = #{age}")
List<User> selectUsersByMap(Map<String, Object> params);
}
调用时,可以构建一个 Map
来传递多个参数:
java
Map<String, Object> params = new HashMap<>();
params.put("name", "Alice");
params.put("age", 25);
List<User> users = userMapper.selectUsersByMap(params);
五、MyBatis 注解式参数处理
MyBatis 支持通过注解定义 SQL 语句,参数的绑定方式与 XML 配置相似。通过注解,开发者可以直接在 Mapper 接口中编写 SQL 语句和参数映射规则。
1. 简单注解参数
可以直接使用 #{}
绑定参数,SQL 语句通过 @Select
、@Insert
、@Update
等注解直接定义在接口方法上。
java
public interface UserMapper {
@Select("SELECT * FROM users WHERE name = #{name} AND age = #{age}")
List<User> selectUsersByNameAndAge(@Param("name") String name, @Param("age") int age);
}
2. 复杂动态 SQL
对于复杂 SQL 或动态 SQL,也可以在注解中实现,配合 MyBatis 的 @Param
进行灵活的参数传递。
java
@Select("<script>" +
"SELECT * FROM users WHERE 1=1 " +
"<if test='name != null'> AND name = #{name} </if>" +
"<if test='age != null'> AND age = #{age} </if>" +
"</script>")
List<User> selectUsersByNameAndAge(@Param("name") String name, @Param("age") Integer age);
在这个示例中,使用了 script
标签和 if
条件标签来实现动态 SQL 查询。
六、MyBatis 参数处理注意事项
1. 避免使用 ${}
直接拼接参数
尽量避免使用 ${}
拼接参数,因为它会直接将参数值插入到 SQL 中,容易引发 SQL 注入风险。除非是动态拼接表名、列名等不可避免的场景,推荐使用 #{}
进行参数绑定。
2. @Param
注解的使用
当传递多个参数时,最好使用 @Param
注解给每个参数命名,以提高代码的可读性,并防止自动生成的 param1
, param2
等名称引发混淆。
3. 参数映射与数据库字段的对应
确保 Java 对象中的字段名与数据库表的列名对应。如果命名不一致,可以使用 @Results
或者 XML 的 <resultMap>
来手动
指定映射关系。
七、总结
MyBatis 提供了丰富的参数处理机制,包括单个参数、多个参数、对象参数和集合参数的处理。通过 #{}
和 @Param
等方式,MyBatis 实现了对 SQL 语句中的参数绑定和动态 SQL 的灵活支持。合理使用 MyBatis 的参数处理机制,能够简化数据库操作代码,同时保持 SQL 语句的灵活性和可读性。