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 属性。
<think>嗯,用户问的是iBATISMyBatis参数传递语法上的主要区别。我需要先回忆一下这两个框架的关系。iBATIS是早期的版本,后来变成了MyBatis,所以它们应该有相似之处,但也有一些语法上的变化。 首先,参数传递方面,iBATIS我记得主要是用#$来引用参数,而MyBatis可能引入了更明确的参数注解,比如@Param。然后,参数传递的方式可能有变化,比如iBATIS可能需要用parameterClass,而MyBatis可能更灵活,不需要指定这个,或者用parameterType。还有,可能MyBatis支持更多的方式,比如直接使用对象属性,或者Map中的键。 然后,参数占位符的写法可能不同。iBATIS中的参数可能是按顺序来的,比如#value#,而MyBatis可能支持命名参数,比如#{param1}或者使用@Param注解后的名字。还有,多参数传递时,iBATIS可能需要封装成Map或者DTO,而MyBatis可以用@Param来指定多个参数名。 接下来,我需要举一些代码例子,比如iBATIS中可能用#name#,而MyBatis#{name}。另外,在传递多个参数的时候,iBATIS可能需要parameterClass="map",而MyBatis可以用@Param注解或者参数名称直接映射。 还需要注意,iBATIS的配置文件中可能使用的是不同的标签或者属性,比如<parameterMap>,而MyBatis可能简化了这些配置,或者用更灵活的方式处理参数映射。 可能还有动态SQL方面的区别,比如MyBatis的OGNL表达式更强大,而iBATIS可能语法不同。不过用户的问题主要集中在参数传递语法上,所以这部分可能不需要深入。 总结一下,主要的区别包括参数占位符的写法(#name# vs#{name})、多参数处理方式(@Param注解)、参数传递的显式声明(parameterClass vs parameterType)、以及参数引用的方式(按顺序vs命名参数)。 然后我需要验证这些点是否正确。比如在iBATIS中,确实使用#variable#的格式,而MyBatis使用#{variable}。对于多个参数,iBATIS可能需要将它们放入一个Map或对象中,而MyBatis允许通过@Param来命名参数,或者在接口方法中直接使用参数名(需要开启某个配置)。 另外,iBATIS的parameterMap可能已经被MyBatis废弃,转而使用更简单的parameterType,或者直接通过属性名映射。 最后,给出具体的代码示例,说明两者的不同写法,并解释每个例子中的关键点。然后根据这些内容,提出相关的问题,比如参数传递的最佳实践、动态SQL的区别、如何防止SQL注入等。</think>iBATIS(MyBatis前身)与MyBatis参数传递语法上的核心区别主要体现在以下几个方面: 1. **参数占位符格式** iBATIS: ```xml <!-- 使用#包裹参数名 --> <select id="findUser" parameterClass="java.lang.String" resultClass="User"> SELECT * FROM users WHERE name = #name# </select> ``` MyBatis: ```xml <!-- 使用#{}包裹参数名 --> <select id="findUser" parameterType="String" resultType="User"> SELECT * FROM users WHERE name = #{name} </select> ``` 2. **多参数传递方式** iBATIS需要封装为Map: ```java Map<String, Object> params = new HashMap<>(); params.put("start", 0); params.put("limit", 10); sqlMap.queryForList("findUsersByPage", params); ``` MyBatis支持@Param注解: ```java List<User> findUsersByPage(@Param("offset") int start, @Param("limit") int size); ``` 3. **参数类型声明** iBATIS使用parameterClass: ```xml <insert id="insertUser" parameterClass="com.example.User"> INSERT INTO users VALUES(#id#, #name#) </insert> ``` MyBatis使用parameterType: ```xml <insert id="insertUser" parameterType="com.example.User"> INSERT INTO users VALUES(#{id}, #{name}) </insert> ``` 4. **动态参数处理** iBATIS通过$符号直接拼接: ```xml <select id="orderByField" parameterClass="map"> SELECT * FROM users ORDER BY $fieldName$ </select> ``` MyBatis明确区分#{}${}: ```xml <select id="orderByField"> SELECT * FROM users ORDER BY ${fieldName} </select> ``` **主要区别总结**: - 占位符格式从`#param#`变为`#{param}` - 参数声明从`parameterClass`改为`parameterType` - MyBatis引入@Param注解处理参数 - 明确区分安全参数绑定(#{})字符串替换(${})
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

冰糖心书房

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

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

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

打赏作者

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

抵扣说明:

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

余额充值