教程 > mybatis 中文教程 > 阅读:100

mybatis 参数——迹忆客-ag捕鱼王app官网

之前见到的所有语句都使用了简单的参数形式。但实际上,参数是 mybatis 非常强大的元素。对于大多数简单的使用场景,你都不需要使用复杂的参数,比如:


上面的这个示例说明了一个非常简单的命名参数映射。鉴于参数类型(parametertype)会被自动设置为 int,这个参数可以随意命名。原始类型或简单数据类型(比如 integer 和 string)因为没有其它属性,会用它们的值来作为参数。 然而,如果传入一个复杂的对象,行为就会有点不一样了。比如:


  insert into users (id, username, password)
  values (#{id}, #{username}, #{password})

如果 user 类型的参数对象传递到了语句中,会查找 id、username 和 password 属性,然后将它们的值传入预处理语句的参数中。

对传递语句参数来说,这种方式真是干脆利落。不过参数映射的功能远不止于此。

首先,和 mybatis 的其它部分一样,参数也可以指定一个特殊的数据类型。

#{property,javatype=int,jdbctype=numeric}

和 mybatis 的其它部分一样,几乎总是可以根据参数对象的类型确定 javatype,除非该对象是一个 hashmap。这个时候,你需要显式指定 javatype 来确保正确的类型处理器(typehandler)被使用。

提示 jdbc 要求,如果一个列允许使用 null 值,并且会使用值为 null 的参数,就必须要指定 jdbc 类型(jdbctype)。阅读 preparedstatement.setnull()的 javadoc 来获取更多信息。

要更进一步地自定义类型处理方式,可以指定一个特殊的类型处理器类(或别名),比如:

#{age,javatype=int,jdbctype=numeric,typehandler=mytypehandler}

参数的配置好像越来越繁琐了,但实际上,很少需要如此繁琐的配置。

对于数值类型,还可以设置 numericscale 指定小数点后保留的位数。

#{height,javatype=double,jdbctype=numeric,numericscale=2}

最后,mode 属性允许你指定 in,out 或 inout 参数。如果参数的 mode 为 out 或 inout,将会修改参数对象的属性值,以便作为输出参数返回。 如果 mode 为 out(或 inout),而且 jdbctype 为 cursor(也就是 oracle 的 refcursor),你必须指定一个 resultmap 引用来将结果集 resultmap 映射到参数的类型上。要注意这里的 javatype 属性是可选的,如果留空并且 jdbctype 是 cursor,它会被自动地被设为 resultmap。

#{department, mode=out, jdbctype=cursor, javatype=resultset, resultmap=departmentresultmap}

mybatis 也支持很多高级的数据类型,比如结构体(structs),但是当使用 out 参数时,你必须显式设置类型的名称。比如(再次提示,在实际中要像这样不能换行):

#{middleinitial, mode=out, jdbctype=struct, jdbctypename=my_type, resultmap=departmentresultmap}

尽管上面这些选项很强大,但大多时候,你只须简单指定属性名,顶多要为可能为空的列指定 jdbctype,其他的事情交给 mybatis 自己去推断就行了。

#{firstname}
#{middleinitial,jdbctype=varchar}
#{lastname}

字符串替换

默认情况下,使用 #{} 参数语法时,mybatis 会创建 preparedstatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样)。 这样做更安全,更迅速,通常也是首选做法,不过有时你就是想直接在 sql 语句中直接插入一个不转义的字符串。 比如 order by 子句,这时候你可以:

order by ${columnname}

这样,mybatis 就不会修改或转义该字符串了。

当 sql 语句中的元数据(如表名或列名)是动态生成的时候,字符串替换将会非常有用。 举个例子,如果你想 select 一个表任意一列的数据时,不需要这样写:

@select("select * from user where id = #{id}")
user findbyid(@param("id") long id);
@select("select * from user where name = #{name}")
user findbyname(@param("name") string name);
@select("select * from user where email = #{email}")
user findbyemail(@param("email") string email);
// 其它的 "findbyxxx" 方法

而是可以只写这样一个方法:

@select("select * from user where ${column} = #{value}")
user findbycolumn(@param("column") string column, @param("value") string value);

其中 ${column} 会被直接替换,而 #{value} 会使用 ? 预处理。 这样,就能完成同样的任务:

user userofid1 = usermapper.findbycolumn("id", 1l);
user userofnamekid = usermapper.findbycolumn("name", "kid");
user userofemail = usermapper.findbycolumn("email", "noone@nowhere.com");

这种方式也同样适用于替换表名的情况。

提示 用这种方式接受用户的输入,并用作语句参数是不安全的,会导致潜在的 sql 注入攻击。因此,要么不允许用户输入这些字段,要么自行转义并检验这些参数。

查看笔记

扫码一下
查看教程更方便
网站地图