单个参数:

    对于单个参数,mybatis不会做处理,#{参数名}:取出参数值

    多个参数:

    多个参数会被封装成一个map

    1. public Employee getEmpByIdAndLastName(Integer id,String lastName);
    2. 封装成的mapkeyparam1,param2...paramN或者参数的索引
    3. 封装成的mapvalue是传入的参数值
    4. 取值时可以用#{param1},#{param2}...

    可以通过@param注解指定封装map时的key

    1. public Employee getEmpByIdAndLastName(@param("id")Integer id,@param("lastName")String lastName);
    2. 通过注解指定后,取值时可以直接#{注解指定的值}这样取值(#{id})

    POJO

    传入的参数是个对象

    1. public void add(@param("employee")Employee employee);
    2. 取值时可以#{employee.属性名},这样取出传入的pojo的属性值

    Map

    如果参数是一个map,可以直接#{key}来取出对应的值

    如果传入的参数是一个Collection(List、Set)类型或者是数组,mybatis会做特殊处理。

    也是把传入的list或者数组封装在map中。

    如果是Collection,key为collection,如果是List,其中也可以用#{list}取值

    如果是数组,则key为array

    1. public Employee getEmpById(List<Integer> ids);
    2. 取值:取出第一个id的值: #{list[0]}

    推荐所有参数都应@param来指定key

    1. ParamNameResolver类解析参数封装map的;
    2. public Employee getEmpByIdAndLastName(@param("id")Integer id,@param("lastName")String lastName);
    3. //构造器主要是为了构建一个names:key为参数的索引,value为参数的名字,{0=id, 1=lastName}
    4. /*确定流程:
    5. 1.获取每个标了param注解的参数的@Param的值:id,lastName; 赋值给name;
    6. 2.每次解析一个参数给map中保存信息:(key:参数索引,value:name的值)
    7. name的值:
    8. 标注了param注解:注解的值
    9. 没有标注:
    10. 1.全局配置:useActualParamName(允许通过方法签名中声明的实际名称引用语句参数jdk1.8以上才有用):name=参数名
    11. 2.name=map.size();相当于当前元素的索引
    12. 构建好的names为:{0=id, 1=lastName}
    13. */
    14. public ParamNameResolver(Configuration config, Method method) {
    15. final Class<?>[] paramTypes = method.getParameterTypes();
    16. final Annotation[][] paramAnnotations = method.getParameterAnnotations();
    17. final SortedMap<Integer, String> map = new TreeMap<Integer, String>();
    18. int paramCount = paramAnnotations.length;
    19. // get names from @Param annotations
    20. for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
    21. if (isSpecialParameter(paramTypes[paramIndex])) {
    22. // skip special parameters
    23. continue;
    24. }
    25. String name = null;
    26. for (Annotation annotation : paramAnnotations[paramIndex]) {
    27. if (annotation instanceof Param) {
    28. hasParamAnnotation = true;
    29. name = ((Param) annotation).value();
    30. break;
    31. }
    32. }
    33. if (name == null) {
    34. // @Param was not specified.
    35. if (config.isUseActualParamName()) {
    36. name = getActualParamName(method, paramIndex);
    37. }
    38. if (name == null) {
    39. // use the parameter index as the name ("0", "1", ...)
    40. // gcode issue #71
    41. name = String.valueOf(map.size());
    42. }
    43. }
    44. map.put(paramIndex, name);
    45. }
    46. names = Collections.unmodifiableSortedMap(map);
    47. }
    48. args2"bing"】:
    49. public Object getNamedParams(Object[] args) {
    50. final int paramCount = names.size();
    51. //1、参数为null直接返回
    52. if (args == null || paramCount == 0) {
    53. return null;
    54. //2、如果只有一个元素,并且没有Param注解;args[0]:单个参数直接返回
    55. } else if (!hasParamAnnotation && paramCount == 1) {
    56. return args[names.firstKey()];
    57. //3、多个元素或者有Param标注
    58. } else {
    59. final Map<String, Object> param = new ParamMap<Object>();
    60. int i = 0;
    61. //4、遍历names集合;{0=id, 1=lastName}
    62. for (Map.Entry<Integer, String> entry : names.entrySet()) {
    63. //names集合的value作为key; names集合的key又作为取值的参考args[0]:args【2,"bing"】:
    64. //eg:{id=args[0]:1,lastName=args[1]:Tom,2=args[2]}
    65. param.put(entry.getValue(), args[entry.getKey()]);
    66. // add generic param names (param1, param2, ...)param
    67. //额外的将每一个参数也保存到map中,使用新的key:param1...paramN
    68. //效果:有Param注解可以#{指定的key},或者#{param1}
    69. final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
    70. // ensure not to overwrite parameter named with @Param
    71. if (!names.containsValue(genericParamName)) {
    72. param.put(genericParamName, args[entry.getKey()]);
    73. }
    74. i++;
    75. }
    76. /*
    77. 构建好的param为{"id":2,"lastName":"bing","param1":1,"param2":"bing"}
    78. 所以取参数时既可以#{id},也可以#{param1}
    79. */
    80. return param;
    81. }
    82. }
    83. }

    #{}和${}的区别:

    1. #{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入
    2. ${}:取出的值直接拼装在sql语句中;会有安全问题;
    3. 大多情况下,我们去参数的值都应该去使用#{};

    原生jdbc不支持占位符的地方我们就可以使用${}进行取值

    比如分表、排序。。。

    select * from ${year}_salary where xxx;

    select * from tbl_employee order by ${order}

    jdbcType:

    在我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理。比如Oracle(报错);

    JdbcType OTHER:无效的类型;因为mybatis对所有的null都映射的是原生Jdbc的OTHER类型,oracle不能正确处理;

    解决:

    1、#{email,jdbcType=NULL};

    2、jdbcTypeForNull默认是OTHER,可以改成NULL

    1. <setting name="jdbcTypeForNull" value="NULL"/>