MyBatis 参数传递

一、#{} 与 ${} 的核心区别

语法 底层实现 编译方式 安全特性 适用场景
#{} PreparedStatement 预编译 防 SQL 注入 大部分参数传递场景(推荐优先用)
${} Statement 字符串拼接 有 SQL 注入风险 表名、列名动态拼接(需手动防注入)

二、参数传递场景与取值方式

1. 单个参数

  • 普通类型(如 Long、String)

    示例方法:Employee getEmpById(Long id);

    XML 取值:#{id}

  • List 类型

    示例方法:List<Employee> getEmpByIds(List<Long> ids);

    XML 取值:#{ids[0]}(取列表第一个元素,可遍历)

  • 对象类型

    示例方法:int addEmp(Employee emp);(Employee 含 nameage 属性)

    XML 取值:#{name}#{age}

  • Map 类型

    示例方法:Employee getEmpByMap(Map<String, Object> map);(map 含 idname 键)

    XML 取值:#{id}#{name}

2. 多个参数

  • 无 @Param 注解(新版 MyBatis 兼容,不推荐):

    示例方法:Employee getEmp(Long id, String name);

    XML 取值:#{param1}(id)、#{param2}(name)

  • 有 @Param 注解(推荐,明确参数名):

    示例方法:Employee getEmp(@Param("id") Long id, @Param("name") String name);

    XML 取值:#{id}#{name}

  • 混合参数(扩展场景)

    示例方法:List<Employee> getEmp(@Param("id") Long id, @Param("ext") Map<String, Object> ext, @Param("ids") List<Long> ids, @Param("emp") Employee emp);

    XML 取值:

    • 单个参数:#{id}
    • Map 内属性:#{ext.name}#{ext.age}
    • List 元素:#{ids[0]}#{ids[1]}
    • 对象属性:#{emp.email}#{emp.age}

三、最佳实践

  1. 优先使用 #{} 进行参数传递,避免 SQL 注入风险。
  2. 若需动态拼接表名、列名(如分表场景),使用 ${} 时必须手动做 SQL 注入防护(如参数白名单校验)。
  3. 即使只有一个参数,也建议使用 @Param 注解明确参数名,提升代码可读性与可维护性。