一、使用参数位置(默认方式)
在 MyBatis 的 mapper
接口中,如果需要传递多个参数,最简单的方法是直接在方法中定义多个参数。MyBatis 会默认将这些参数绑定为 param1
, param2
, param3
等等,并按照参数的顺序进行绑定。
示例代码
public interface UserMapper {
@Select("SELECT * FROM users WHERE name = #{param1} AND age = #{param2}")
User selectByNameAndAge(String name, int age);
}
在上面的代码中,selectByNameAndAge
方法接受两个参数 name
和 age
,在 SQL 语句中,#{param1}
和 #{param2}
分别对应 name
和 age
参数。
适用场景
这种方式适用于参数数量较少的场景,一般在参数数量不超过三个时使用较为方便。
缺点
- 参数的顺序必须严格一致,如果参数的顺序发生变化,绑定的结果可能会错误。
- 参数的命名较为模糊,不利于代码的可读性。
二、使用 @Param
注解
为了增强参数的可读性和灵活性,MyBatis 提供了 @Param
注解,允许开发者为每个参数指定一个明确的名称。这样,在 SQL 语句中可以通过名称来引用参数,而不必依赖参数的位置。
示例代码
public interface UserMapper {
@Select("SELECT * FROM users WHERE name = #{name} AND age = #{age}")
User selectByNameAndAge(@Param("name") String name, @Param("age") int age);
}
在这个示例中,@Param("name")
和 @Param("age")
指定了参数的名称,因此在 SQL 语句中可以通过 #{name}
和 #{age}
来引用它们。
适用场景
这种方式适用于参数较多的场景,并且参数名称明确,有助于提高代码的可读性和维护性。
优点
- 参数名称明确,有助于提高代码的可读性。
- 可以自由调整方法参数的顺序,而不影响 SQL 中的参数绑定。
三、使用 Map
传递多个参数
如果需要传递大量参数,或者参数在运行时是动态的,使用 Map
是一种很灵活的方式。Map
的键作为参数的名称,值作为参数的值。
示例代码
public interface UserMapper {
@Select("SELECT * FROM users WHERE name = #{name} AND age = #{age}")
User selectByNameAndAge(Map<String, Object> params);
}
调用时可以这样传递参数:
Map<String, Object> params = new HashMap<>();
params.put("name", "John");
params.put("age", 25);
User user = userMapper.selectByNameAndAge(params);
在 SQL 语句中,#{name}
和 #{age}
会分别绑定到 Map
中的 name
和 age
键对应的值。
适用场景
- 适合参数数量不确定或动态生成的场景。
- 在传递复杂的动态查询条件时非常有用。
优点
- 灵活性强,可以根据需求动态添加或移除参数。
- 适合动态 SQL 构建,特别是在条件查询或复杂查询中。
缺点
- 使用
Map
时,键值对的错误使用(如拼写错误)难以检测,可能导致运行时错误。 - 参数名称需要手动维护,容易出错。
四、使用 Java 对象传递多个参数
在 MyBatis 中,可以将多个参数封装在一个 Java 对象中,并在 mapper
方法中传递该对象。这种方式特别适用于参数较多且具有逻辑关系的情况。
示例代码
public class UserQuery {
private String name;
private int age;
// 省略 getter 和 setter
}
public interface UserMapper {
@Select("SELECT * FROM users WHERE name = #{name} AND age = #{age}")
User selectByQuery(UserQuery query);
}
调用时只需创建一个 UserQuery
对象:

UserQuery query = new UserQuery();
query.setName("John");
query.setAge(25);
User user = userMapper.selectByQuery(query);
在 SQL 语句中,#{name}
和 #{age}
会自动绑定到 UserQuery
对象中的 name
和 age
属性。
适用场景
- 适合参数较多且具有逻辑关系的场景,如查询条件封装、批量更新等。
- 适合复杂业务逻辑,且可能需要多次传递相同参数的情况。
优点
- 参数封装在对象中,结构清晰,易于维护。
- 可以复用相同的对象类型,减少重复代码。
缺点
- 需要为每种参数组合创建一个 Java 对象,可能会增加类的数量,尤其在参数组合较多的情况下。
五、使用多个对象作为参数
MyBatis 允许传递多个对象作为方法参数。这种方式通常结合 @Param
注解使用,每个对象都可以在 SQL 语句中通过自定义的名称引用。
示例代码
public class User {
private String name;
// 省略其他属性和方法
}
public class UserRole {
private String role;
// 省略其他属性和方法
}
public interface UserMapper {
@Select("SELECT * FROM users WHERE name = #{user.name} AND role = #{role.role}")
User selectByUserAndRole(@Param("user") User user, @Param("role") UserRole role);
}
调用时:
User user = new User();
user.setName("John");
UserRole role = new UserRole();
role.setRole("Admin");
User result = userMapper.selectByUserAndRole(user, role);
在 SQL 语句中,#{user.name}
和 #{role.role}
分别绑定到 User
和 UserRole
对象中的属性。
适用场景
- 适合复杂业务逻辑,多个对象之间有明确的逻辑关联。
- 适合分层次传递参数,如用户信息与角色信息分别封装在不同的对象中。
优点
- 参数的分层次传递,结构更加清晰。
- 可以直接在 SQL 中引用对象的属性,减少参数命名的复杂度。
缺点
- 如果传递的对象较多,可能会增加方法签名的复杂度。
- 需要维护多个对象,可能增加类的数量。
六、总结
MyBatis 提供了多种方式来传递多个参数,从最简单的参数位置绑定到灵活的 Map
和 Java 对象封装,每种方式都有其适用场景和优缺点。在实际开发中,选择合适的参数传递方式可以提高代码的可读性、维护性和灵活性。
- 参数位置绑定 适合简单场景,适用性较低。
@Param
注解 提高了代码的可读性和灵活性,是推荐的方式之一。Map
传递参数 适合动态和不确定参数的场景,灵活性最高,但也容易出错。- Java 对象封装 适合复杂业务逻辑和参数多的场景,代码结构清晰,易于维护。
- 多个对象作为参数 适合分层次的复杂参数传递,结构清晰但复杂度较高。
在实际项目中,应根据具体需求选择最适合的方式,以实现最佳的代码质量和性能。