Mybatis入門(mén)程序數(shù)據(jù)操作(3)

內(nèi)容接著上一篇文章,Mybatis搭建環(huán)境(2)

先把dao層的接口給出來(lái),和UserMapper.xml中的mapper標(biāo)簽的namespace屬性對(duì)接邓萨。

package cn.com.mybatis.dao;
import cn.com.mybatis.po.User;

public interface UserDao {
    User findUserById(int id);
    User findUserByUsername(String username);
    int insertUser(User user);
    int deleteUser(int id);
    User updateUserName(String username);
}

1. 模糊查詢樣例

要對(duì)數(shù)據(jù)庫(kù)中User表的數(shù)據(jù)進(jìn)行模糊查詢冰寻,需要通過(guò)匹配名字的某個(gè)字來(lái)查詢?cè)撚脩艟踉模紫仍赨serMapper.xml文件中配置SQL映射:

<!--根據(jù)用戶姓名進(jìn)行模糊查詢-->
<select id="findUserByUsername" parameterType="java.lang.String" resultType="cn.com.mybatis.po.User">
    SELECT * FROM USER WHERE username LIKE '%${value}'
</select>

這里“${}”符號(hào)表示拼接SQL串,將收到的參數(shù)內(nèi)容不加任何修飾地拼接在SQL中嗜闻,在“${}”中只能使用value代表其中的參數(shù)蜕依。然而在Web項(xiàng)目中,如果沒(méi)有防范SQL注入的機(jī)制琉雳,要謹(jǐn)慎使用“${}”符號(hào)拼接SQL語(yǔ)句串样眠,因?yàn)檫@可能會(huì)引起SQL注入的風(fēng)險(xiǎn)。
然后在MyBatisTest測(cè)試類(lèi)中寫(xiě)一個(gè)新的測(cè)試方法TestFuzzySearch翠肘,來(lái)查詢所有名稱中含有“麗”字的用戶信息檐束。

@Test
    public void TestFuzzySearch() throws IOException{
        SqlSession sqlSession = dataConn.getSqlSession();
        List<User> userList = sqlSession.selectList("cn.com.mybatis.dao.UserDao.findUserByUsername","麗");
        for(User user : userList){
            System.out.println("姓名:"+user.getUsername());
            System.out.println("性別:"+user.getGender());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            System.out.println("生日:"+sdf.format(user.getBirthday()));
            System.out.println("所在地:"+user.getProvince()+user.getCity());
        }
        sqlSession.close();;
    }
模糊查詢結(jié)果.png

2. 新增樣例

要對(duì)數(shù)據(jù)庫(kù)中User表進(jìn)行新增數(shù)據(jù),在UserMapper.xml文件中配置SQL映射:

<!--在表中新增數(shù)據(jù)信息-->
<insert id="insertUser" parameterType="cn.com.mybatis.po.User">
    INSERT INTO USER(username, password, gender, birthday, email, province, city)
      VALUE (#{username}, #{password}, #{gender}, #{birthday,jdbcType=DATE}, #{email}, #{province}, #{city})
</insert>

在測(cè)試類(lèi)MyBatisTest中添加名為T(mén)estInsert方法锯茄,向User表新插入一條用戶數(shù)據(jù)厢塘。

@Test
public void TestInsert() throws Exception{
    SqlSession sqlSession = dataConn.getSqlSession();
    User user = new User();
    user.setUsername("孫佳佳");
    user.setGender("男");
    user.setPassword("5555");
    user.setEmail("5555@126.com");
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    user.setBirthday(sdf.parse("1991-02-16"));
    user.setProvince("湖北省");
    user.setCity("武漢市");
    sqlSession.insert("cn.com.mybatis.dao.UserDao.insertUser",user);
    sqlSession.commit();
    sqlSession.close();
}
插入數(shù)據(jù)成功頁(yè)面.png

更新后的表單信息.png

如果想在插入之后不執(zhí)行查詢語(yǔ)句而立即獲取id信息,有兩種方法肌幽,這里針對(duì)Mysql為例:

    1. 通過(guò)Mysql的函數(shù)SELECT LAST_INSERT_ID()來(lái)獲取剛剛插入記錄的自增主鍵(即取出最后一個(gè)主鍵)晚碾。
      這里order參數(shù)表示該SQL函數(shù)相對(duì)于insert語(yǔ)句的執(zhí)行時(shí)間,有BEFORE和AFTER喂急。這里程序執(zhí)行完insert之后格嘁,就可以在測(cè)試類(lèi)中,從user對(duì)象中直接拿到該id的信息(取出的主鍵信息會(huì)放置在輸入?yún)?shù)user對(duì)象中)廊移。
<!--在表中新增數(shù)據(jù)信息-->
<insert id="insertUser" parameterType="cn.com.mybatis.po.User">
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
        SELECT LAST_INSERT_ID()
    </selectKey>
    INSERT INTO USER(username, password, gender, birthday, email, province, city)
      VALUE (#{username}, #{password}, #{gender}, #{birthday,jdbcType=DATE}, #{email}, #{province}, #{city})
</insert>
    1. 在insert標(biāo)簽中添加屬性“useGenerateKeys”和“keyProperty”,其中userGeneratedKeys表示使用自增主鍵糕簿,而keyProperty是Java對(duì)象的屬性名。
<!--在表中新增數(shù)據(jù)信息-->
<insert id="insertUser" parameterType="cn.com.mybatis.po.User"
    useGeneratedKeys="true" keyProperty="id">
    INSERT INTO USER(username, password, gender, birthday, email, province, city)
      VALUE (#{username}, #{password}, #{gender}, #{birthday,jdbcType=DATE}, #{email}, #{province}, #{city})
</insert>

進(jìn)行完上面的配置后狡孔,MyBatis執(zhí)行完insert語(yǔ)句后懂诗,會(huì)自動(dòng)將自增長(zhǎng)id值賦給對(duì)象User的屬性id,然后在邏輯處理層就可以通過(guò)User的get方法獲得該id苗膝。

3. 刪除與修改樣例

對(duì)于刪除和修改殃恒,同樣需要在UserMapper.xml配置文件中編寫(xiě)相關(guān)的SQL配置:

<!--刪除用戶-->
<delete id="deleteUser" parameterType="java.lang.Integer">
    DELETE FROM USER WHERE id=#{id}
</delete>
<!--修改用戶-->
<update id="updateUserName" parameterType="cn.com.mybatis.po.User">
    UPDATE USER SET username=#{username} where id=#{id}
</update>

在MyBatisTest測(cè)試類(lèi)中添加TestDelete和TestUpdate測(cè)試方法:

@Test
public void TestDelete() throws Exception{
    SqlSession sqlSession = dataConn.getSqlSession();
    sqlSession.delete("cn.com.mybatis.dao.UserDao.deleteUser",5);
    sqlSession.commit();
    sqlSession.close(); 
}
@Test
public void TestUpdate() throws Exception{
    SqlSession sqlSession = dataConn.getSqlSession();
    User user = new User();
    user.setId(4);
    user.setUsername("孫麗");
    sqlSession.update("cn.com.mybatis.dao.UserDao.updateUserName", user);
    sqlSession.commit();
    sqlSession.close();
}
刪除樣例成功.png

修改樣例成功.png

到此Mybatis的基本入門(mén)操作就完成了,下面補(bǔ)充一下注意的事項(xiàng):

  • 關(guān)于parameterType:
    在執(zhí)行SQL配置時(shí)辱揭,需要指定輸入?yún)?shù)的類(lèi)型离唐。parameterType就是用來(lái)在SQL映射文件指定輸入?yún)?shù)類(lèi)型的。使用parameterType可以指定參數(shù)為基本數(shù)據(jù)類(lèi)型(如 int问窃、float等)亥鬓、包裝數(shù)據(jù)類(lèi)型(Integer類(lèi)、Double類(lèi))以及用戶編寫(xiě)的JavaBean封裝類(lèi)域庇。
  • 關(guān)于resultType:
    在加載SQL配置嵌戈,并綁定制定輸入?yún)?shù)和運(yùn)行SQL之后覆积,會(huì)得到數(shù)據(jù)庫(kù)返回的相應(yīng)結(jié)果,此時(shí)使用resultType來(lái)指定數(shù)據(jù)庫(kù)返回的信息對(duì)應(yīng)Java的數(shù)據(jù)類(lèi)型咕别。輸出參數(shù)的類(lèi)型為基本數(shù)據(jù)類(lèi)型(如 int技健、float等)、包裝數(shù)據(jù)類(lèi)型(Integer類(lèi)惰拱、Double類(lèi))以及用戶自己編寫(xiě)的JavaBean的封裝類(lèi)妥凳。
  • 關(guān)于“#{}”:
    在SQL配置文件中咒循,輸入?yún)?shù)需要占位符來(lái)標(biāo)識(shí)對(duì)應(yīng)的位置。在傳統(tǒng)的JDBC的編程中凯旋,占位符用"?"來(lái)表示馋没,然后在加載SQL之前按照"?"的位置設(shè)置參數(shù)昔逗。在MyBatis中也是一種占位符,它接受輸入?yún)?shù)篷朵,在大括號(hào)中編寫(xiě)參數(shù)名稱來(lái)接受對(duì)應(yīng)參數(shù)勾怒。“#{}”接受的可以是簡(jiǎn)單類(lèi)型声旺、普通JavaBean或者HashMap笔链。里面可以寫(xiě)value或者其他名稱。若接受的是JavaBean腮猖,它通過(guò)OGNL讀取對(duì)象中的屬性值鉴扫,通過(guò)“屬性1.屬性2.屬性3等”的方式獲取對(duì)象屬性值。
  • 關(guān)于“${}”:
    在SQL配置中澈缺,有時(shí)需要拼接SQL語(yǔ)句坪创。例如在模糊查詢時(shí),就需要在查詢條件的兩側(cè)拼接兩個(gè)“%”字符串姐赡,這時(shí)“#{}”就不行莱预。在MyBatis中,“${}”在SQL配置文件中表示的是一個(gè)“拼接符號(hào)”项滑,可以在原有SQL語(yǔ)句上拼接新的符合SQL語(yǔ)法的語(yǔ)句依沮。單用“${}”會(huì)引起SQL注入,慎用杖们。另外悉抵,當(dāng)接受簡(jiǎn)單類(lèi)型時(shí),“${}”中只能寫(xiě)“value”摘完,而不能寫(xiě)其他名稱姥饰。其他內(nèi)容同上。

注意 ${} 和 #{} 的區(qū)別:

動(dòng)態(tài) sql 是 mybatis 的主要特性之一孝治,在 mapper 中定義的參數(shù)傳到 xml 中之后列粪,在查詢之前 mybatis 會(huì)對(duì)其進(jìn)行動(dòng)態(tài)解析审磁。mybatis 為我們提供了兩種支持動(dòng)態(tài) sql 的語(yǔ)法:#{} 以及 ${}。

  • ${}哪邊都能使用岂座,只是存在sql注入風(fēng)險(xiǎn)态蒂,相當(dāng)于直接拼接字符串,不對(duì)參數(shù)做任何處理费什。
  • #{}會(huì)進(jìn)行預(yù)編譯钾恢,對(duì)參數(shù)進(jìn)行處理,防止注入鸳址。
<!--在下面的語(yǔ)句中瘩蚪,如果 username 的值為 zhangsan,則兩種方式無(wú)任何區(qū)別:-->
select * from user where name = #{name};
select * from user where name = ${name};
<!--解析出來(lái)的結(jié)果都是如下:-->
select * from user where name = 'zhangsan';
  • 但是 #{} 和 ${} 在預(yù)編譯中的處理是不一樣的稿黍。#{} 在預(yù)處理時(shí)疹瘦,會(huì)把參數(shù)部分用一個(gè)占位符 ? 代替,變成如下的 sql 語(yǔ)句:
elect * from user where name = ?;
  • 而 ${} 則只是簡(jiǎn)單的字符串替換巡球,在動(dòng)態(tài)解析階段言沐,該 sql 語(yǔ)句會(huì)被解析成:
select * from user where name = 'zhangsan';
  • 以上,#{} 的參數(shù)替換是發(fā)生在 DBMS 中酣栈,而 ${} 則發(fā)生在動(dòng)態(tài)解析過(guò)程中险胰。
    那么,在使用過(guò)程中我們應(yīng)該使用哪種方式呢钉嘹?
    答案是鸯乃,優(yōu)先使用 #{}。因?yàn)?${} 會(huì)導(dǎo)致 sql 注入的問(wèn)題跋涣∮看下面的例子:
select * from ${tableName} where name = #{name}
<!--若表名為user; delete user; 則動(dòng)態(tài)解析之后 sql 如下:-- -->
select * from user; delete user; -- where name = ?;

之后的語(yǔ)句被注釋掉,而原本查詢用戶的語(yǔ)句變成了查詢所有用戶信息+刪除用戶表的語(yǔ)句陈辱,會(huì)對(duì)數(shù)據(jù)庫(kù)造成重大損傷奖年,極大可能導(dǎo)致服務(wù)器宕機(jī)

  • 既然這樣那為什么還要用${}呢。
    因?yàn)槭褂?{}存在一個(gè)不足沛贪,當(dāng)參數(shù)為字符串時(shí)會(huì)加上'',這就導(dǎo)致某些情況下sql失效陋守。
    SELECT * FROM #{tableName},當(dāng)使用#{}傳入?yún)?shù)user利赋,sql就會(huì)變成
    SELECT * FROM 'user'. 這樣就會(huì)報(bào)錯(cuò)查詢不到數(shù)據(jù)

參考文章: Mabatis中#{}和${}的區(qū)別 水评、mybatis #{}與${}使用場(chǎng)景

  • 關(guān)于“selectOne”與“selectList”:
    它們都屬于SqlSession類(lèi)提供的方法,在使用查詢語(yǔ)句時(shí)媚送,如果查詢的數(shù)據(jù)只有一條數(shù)據(jù)中燥,那么可以使用“selectOne”方法進(jìn)行查詢;如果查詢的數(shù)據(jù)可能多于一條塘偎,那么可以使用“selectList”方法進(jìn)行查詢疗涉。
  • MyBatis與Hibernate區(qū)別:
    MyBatis的特點(diǎn)就是以SQL語(yǔ)句為核心的不完全的ORM(關(guān)系型映射)框架拿霉。與Hiberna相比,Hibernate的學(xué)習(xí)成本比較高咱扣,而SQL語(yǔ)句并不需要開(kāi)發(fā)人員完成绽淘,只需調(diào)用相關(guān)API即可。這對(duì)于開(kāi)發(fā)效率是一個(gè)優(yōu)勢(shì)闹伪,但是缺點(diǎn)時(shí)沒(méi)辦法對(duì)SQL語(yǔ)句進(jìn)行優(yōu)化和修改沪铭。而MyBatis雖然需要開(kāi)發(fā)人員自己配置SQL語(yǔ)句,MyBatis來(lái)實(shí)現(xiàn)映射關(guān)系偏瓤,但是這樣的項(xiàng)目可以適應(yīng)經(jīng)常變化的項(xiàng)目需求伦意。所以,使用MyBatis的場(chǎng)景是:對(duì)SQL優(yōu)化要求比較高硼补,或是項(xiàng)目需求或業(yè)務(wù)經(jīng)常變動(dòng)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末熏矿,一起剝皮案震驚了整個(gè)濱河市已骇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌票编,老刑警劉巖褪储,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異慧域,居然都是意外死亡鲤竹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)昔榴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)辛藻,“玉大人,你說(shuō)我怎么就攤上這事互订≈。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵仰禽,是天一觀的道長(zhǎng)氮墨。 經(jīng)常有香客問(wèn)我,道長(zhǎng)吐葵,這世上最難降的妖魔是什么规揪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮温峭,結(jié)果婚禮上猛铅,老公的妹妹穿的比我還像新娘。我一直安慰自己诚镰,他們只是感情好奕坟,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布祥款。 她就那樣靜靜地躺著,像睡著了一般月杉。 火紅的嫁衣襯著肌膚如雪刃跛。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,021評(píng)論 1 291
  • 那天苛萎,我揣著相機(jī)與錄音桨昙,去河邊找鬼。 笑死腌歉,一個(gè)胖子當(dāng)著我的面吹牛蛙酪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播翘盖,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼桂塞,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了馍驯?” 一聲冷哼從身側(cè)響起阁危,我...
    開(kāi)封第一講書(shū)人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎汰瘫,沒(méi)想到半個(gè)月后狂打,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡混弥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年趴乡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝗拿。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡晾捏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蛹磺,到底是詐尸還是另有隱情粟瞬,我是刑警寧澤,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布萤捆,位于F島的核電站裙品,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏俗或。R本人自食惡果不足惜市怎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辛慰。 院中可真熱鬧区匠,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至戚篙,卻和暖如春五鲫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背岔擂。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工位喂, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乱灵。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓塑崖,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親痛倚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子规婆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容