99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

MyBatis 3 XML映射文件-參數(shù)

2022-04-09 13:52 更新

之前見(jiàn)到的所有語(yǔ)句都使用了簡(jiǎn)單的參數(shù)形式。但實(shí)際上,參數(shù)是 MyBatis 非常強(qiáng)大的元素。對(duì)于大多數(shù)簡(jiǎn)單的使用場(chǎng)景,你都不需要使用復(fù)雜的參數(shù),比如:

<select id="selectUsers" resultType="User">
  select id, username, password
  from users
  where id = #{id}
</select>

上面的這個(gè)示例說(shuō)明了一個(gè)非常簡(jiǎn)單的命名參數(shù)映射。鑒于參數(shù)類型(?parameterType?)會(huì)被自動(dòng)設(shè)置為 int,這個(gè)參數(shù)可以隨意命名。原始類型或簡(jiǎn)單數(shù)據(jù)類型(比如 Integer 和 String)因?yàn)闆](méi)有其它屬性,會(huì)用它們的值來(lái)作為參數(shù)。 然而,如果傳入一個(gè)復(fù)雜的對(duì)象,行為就會(huì)有點(diǎn)不一樣了。比如:

<insert id="insertUser" parameterType="User">
  insert into users (id, username, password)
  values (#{id}, #{username}, #{password})
</insert>

如果 User 類型的參數(shù)對(duì)象傳遞到了語(yǔ)句中,會(huì)查找 ?id?、?username ?和 ?password ?屬性,然后將它們的值傳入預(yù)處理語(yǔ)句的參數(shù)中。

對(duì)傳遞語(yǔ)句參數(shù)來(lái)說(shuō),這種方式真是干脆利落。不過(guò)參數(shù)映射的功能遠(yuǎn)不止于此。

首先,和 MyBatis 的其它部分一樣,參數(shù)也可以指定一個(gè)特殊的數(shù)據(jù)類型。

#{property,javaType=int,jdbcType=NUMERIC}

和 MyBatis 的其它部分一樣,幾乎總是可以根據(jù)參數(shù)對(duì)象的類型確定 ?javaType?,除非該對(duì)象是一個(gè) ?HashMap?。這個(gè)時(shí)候,你需要顯式指定 ?javaType ?來(lái)確保正確的類型處理器(?TypeHandler?)被使用。

?JDBC ?要求,如果一個(gè)列允許使用 ?null ?值,并且會(huì)使用值為 ?null ?的參數(shù),就必須要指定 ?JDBC ?類型(?jdbcType?)。

要更進(jìn)一步地自定義類型處理方式,可以指定一個(gè)特殊的類型處理器類(或別名),比如:

#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}

參數(shù)的配置好像越來(lái)越繁瑣了,但實(shí)際上,很少需要如此繁瑣的配置。

對(duì)于數(shù)值類型,還可以設(shè)置 ?numericScale ?指定小數(shù)點(diǎn)后保留的位數(shù)。

#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}

最后,?mode ?屬性允許你指定 ?IN?,?OUT ?或 ?INOUT ?參數(shù)。如果參數(shù)的 ?mode ?為 ?OUT ?或 ?INOUT?,將會(huì)修改參數(shù)對(duì)象的屬性值,以便作為輸出參數(shù)返回。 如果 ?mode ?為 ?OUT?(或 ?INOUT?),而且 ?jdbcType ?為 ?CURSOR?(也就是 ?Oracle ?的 ?REFCURSOR?),你必須指定一個(gè) ?resultMap ?引用來(lái)將結(jié)果集 ?ResultMap ?映射到參數(shù)的類型上。要注意這里的 ?javaType ?屬性是可選的,如果留空并且 ?jdbcType ?是 ?CURSOR?,它會(huì)被自動(dòng)地被設(shè)為 ?ResultMap?。

#{department, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=departmentResultMap}

MyBatis 也支持很多高級(jí)的數(shù)據(jù)類型,比如結(jié)構(gòu)體(structs),但是當(dāng)使用 out 參數(shù)時(shí),你必須顯式設(shè)置類型的名稱。比如(再次提示,在實(shí)際中要像這樣不能換行):

#{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}

盡管上面這些選項(xiàng)很強(qiáng)大,但大多時(shí)候,你只須簡(jiǎn)單指定屬性名,頂多要為可能為空的列指定 ?jdbcType?,其他的事情交給 MyBatis 自己去推斷就行了。

#{firstName}
#{middleInitial,jdbcType=VARCHAR}
#{lastName}

字符串替換

默認(rèn)情況下,使用 ?#{}? 參數(shù)語(yǔ)法時(shí),MyBatis 會(huì)創(chuàng)建 ?PreparedStatement ?參數(shù)占位符,并通過(guò)占位符安全地設(shè)置參數(shù)(就像使用 ? 一樣)。 這樣做更安全,更迅速,通常也是首選做法,不過(guò)有時(shí)你就是想直接在 SQL 語(yǔ)句中直接插入一個(gè)不轉(zhuǎn)義的字符串。 比如 ORDER BY 子句,這時(shí)候你可以:

ORDER BY ${columnName}

這樣,MyBatis 就不會(huì)修改或轉(zhuǎn)義該字符串了。

當(dāng) SQL 語(yǔ)句中的元數(shù)據(jù)(如表名或列名)是動(dòng)態(tài)生成的時(shí)候,字符串替換將會(huì)非常有用。 舉個(gè)例子,如果你想 select 一個(gè)表任意一列的數(shù)據(jù)時(shí),不需要這樣寫:

@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" 方法

而是可以只寫這樣一個(gè)方法:

@Select("select * from user where ${column} = #{value}")
User findByColumn(@Param("column") String column, @Param("value") String value);

其中 ?${column}? 會(huì)被直接替換,而 ?#{value}? 會(huì)使用 ??? 預(yù)處理。 這樣,就能完成同樣的任務(wù):

User userOfId1 = userMapper.findByColumn("id", 1L);
User userOfNameKid = userMapper.findByColumn("name", "kid");
User userOfEmail = userMapper.findByColumn("email", "noone@nowhere.com");

這種方式也同樣適用于替換表名的情況。

用這種方式接受用戶的輸入,并用作語(yǔ)句參數(shù)是不安全的,會(huì)導(dǎo)致潛在的 SQL 注入攻擊。因此,要么不允許用戶輸入這些字段,要么自行轉(zhuǎn)義并檢驗(yàn)這些參數(shù)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)