MyBatis 如何处理参数? 支持哪些参数类型? 如何传递多个参数? 如何使用 # 和 $ 占位符?

MyBatis 如何处理参数:

  1. 参数解析: 当 MyBatis 执行 SQL 语句时,它会解析 SQL 语句中的占位符(#{}${}),并根据 Mapper 接口方法的参数类型和名称(或 @Param 注解指定的名称)来查找对应的参数值。
  2. 类型转换: MyBatis 会使用 TypeHandler 将 Java 类型的参数值转换为 JDBC 类型的值。
  3. 参数绑定: MyBatis 会使用 PreparedStatement 对象将参数值绑定到 SQL 语句中的占位符。对于 #{} 占位符,MyBatis 会使用 PreparedStatementsetXXX() 方法进行参数绑定,从而防止 SQL 注入;对于 ${} 占位符,MyBatis 会直接将参数值拼接到 SQL 语句中,存在 SQL 注入风险。

MyBatis 支持的参数类型:

MyBatis 支持以下参数类型:

  • 基本类型及其包装类: int, long, float, double, boolean, byte, short, Integer, Long, Float, Double, Boolean, Byte, Short
  • String: 字符串类型。
  • Date: java.util.Datejava.sql.Datejava.sql.Timejava.sql.Timestamp
  • BigDecimal: 高精度数字类型。
  • 数组: 基本类型数组或对象数组。
  • 集合: ListSetMap
  • JavaBean (POJO): 普通 Java 对象。
  • 枚举类型: 默认使用枚举的名称或序数(可以通过自定义 TypeHandler 来改变)。
  • null: 如果传递的是null值, 并且MyBatis无法推断, 则必须指定 jdbcType 属性。

传递多个参数的方式:

MyBatis 提供了多种方式来传递多个参数:

  1. 使用 @Param 注解 (推荐):

    • 在 Mapper 接口方法的参数列表中,使用 @Param 注解为每个参数指定一个名称。
    • 在 SQL 映射文件中,使用 #{} 占位符引用参数时,使用 @Param 注解指定的名称。
    // Mapper 接口
    public interface UserMapper {
        List<User> selectUsersByNameAndAge(@Param("name") String name, @Param("age") int age);
    }
    
    <!-- SQL 映射文件 -->
    <select id="selectUsersByNameAndAge" resultType="com.example.model.User">
        SELECT * FROM users WHERE name LIKE #{name} AND age > #{age}
    </select>
    
  2. 使用 Map:

    • 将多个参数封装到一个 Map 对象中。
    • 在 SQL 映射文件中,使用 #{} 占位符引用参数时,使用 Map 中的 key 作为参数名称。
    // Mapper 接口
    public interface UserMapper {
        List<User> selectUsersByMap(Map<String, Object> params);
    }
    
    // 调用示例
    Map<String, Object> params = new HashMap<>();
    params.put("name", "John%");
    params.put("age", 30);
    List<User> users = userMapper.selectUsersByMap(params);
    
    <!-- SQL 映射文件 -->
    <select id="selectUsersByMap" resultType="com.example.model.User">
        SELECT * FROM users WHERE name LIKE #{name} AND age > #{age}
    </select>
    
  3. 使用 JavaBean (POJO):

    • 将多个参数封装到一个 JavaBean 对象中。
    • 在 SQL 映射文件中,使用 #{} 占位符引用参数时,使用 JavaBean 对象的属性名作为参数名称。
    // JavaBean
    public class UserQuery {
        private String name;
        private int age;
        // getter 和 setter 方法
    }
    
    // Mapper 接口
    public interface UserMapper {
        List<User> selectUsersByQuery(UserQuery query);
    }
    
    // 调用示例
    UserQuery query = new UserQuery();
    query.setName("John%");
    query.setAge(30);
    List<User> users = userMapper.selectUsersByQuery(query);
    
    <!-- SQL 映射文件 -->
    <select id="selectUsersByQuery" resultType="com.example.model.User">
        SELECT * FROM users WHERE name LIKE #{name} AND age > #{age}
    </select>
    
  4. 使用参数索引 (不推荐):

    • 如果不使用 @Param 注解,MyBatis 会按照参数在方法参数列表中的顺序,为参数分配索引(从 0 开始)。
    • 在 SQL 映射文件中,可以使用 #{0}, #{1}, #{param1}, #{param2} 等方式引用参数。 这种方式不够直观,容易出错,不推荐使用。

#$ 占位符的区别:

  • #{} (预编译参数):

    • MyBatis 会使用 PreparedStatementsetXXX() 方法将参数值绑定到 SQL 语句中的占位符。
    • 优点:
      • 防止 SQL 注入: PreparedStatement 会对参数值进行转义,有效防止 SQL 注入攻击。
      • 类型安全: MyBatis 会根据参数类型选择合适的 setXXX() 方法,避免类型转换错误。
      • 性能更好: PreparedStatement 可以预编译 SQL 语句,对于重复执行的 SQL 语句,性能更好。
    • 适用场景: 绝大多数情况,推荐使用 #{}
  • ${} (字符串替换):

    • MyBatis 会直接将参数值拼接到 SQL 语句中。
    • 缺点:
      • SQL 注入风险: 如果参数值来自用户输入,直接使用 ${} 拼接 SQL 语句会导致 SQL 注入漏洞。
      • 类型不安全: MyBatis 不会进行类型转换,可能导致类型错误。
    • 适用场景:
      • 动态表名或列名: 当需要动态指定表名或列名时,可以使用 ${}
      • IN 语句: 当需要将一个集合作为 IN 语句的参数时,可以使用 ${}(但更推荐使用 <foreach> 标签)。
      • ORDER BY: 当需要动态指定排序字段时, 可以使用${}
    <!-- 动态表名 (谨慎使用) -->
    <select id="selectFromTable" resultType="com.example.model.User">
        SELECT * FROM ${tableName} WHERE id = #{id}
    </select>
    
    <!-- IN 语句 (更推荐使用 <foreach> 标签) -->
    <select id="selectUsersByIds" resultType="com.example.model.User">
      SELECT * FROM users WHERE id IN (${ids})
    </select>
    

总结:

  • MyBatis 支持多种参数类型,包括基本类型、String、Date、BigDecimal、数组、集合、JavaBean、枚举类型等。
  • 传递多个参数的推荐方式是使用 @Param 注解。
  • #{} 是预编译参数,可以防止 SQL 注入,类型安全,性能更好,推荐使用。
  • ${} 是字符串替换,存在 SQL 注入风险,类型不安全,谨慎使用,仅在需要动态表名、列名或 IN 语句等特殊场景下使用。
  • 传递 null值, 并且MyBatis无法推断, 则必须指定 jdbcType 属性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值