Mybatis之旅第二篇-Mapper動態代理方式

一、引言

通過上一篇mybatis的入門學習,我們已經會使用mybatis實現簡單的增刪改查,但是我們也發現了用原始Dao開發的一些問題:

Dao方法體存在重復代碼:通過SqlSessionFactory創建SqlSession,調用SqlSession的數據庫操作方法

調用sqlSession的數據庫操作方法需要指定statement的id,這里存在硬編碼,不得于開發維護。

為了解決這些問題,我們采用Mapper動態代理方法來進行開發:程序員編寫Mapper接口(相當于Dao接口),由Mybatis框架根據接口定義創建接口的動態代理對象,代理對象的方法體同上邊Dao接口實現類方法。

二、開發規范

Mapper接口開發需要遵循以下規范:

1、 Mapper.xml文件中的namespace與mapper接口的類路徑相同。

2、 Mapper接口方法名和Mapper.xml中定義的每個statement的id相同

3、 Mapper接口方法的輸入參數類型和mapper.xml中定義的每個sql 的parameterType的類型相同

4、Mapper接口方法的輸出參數類型和mapper.xml中定義的每個sql的resultType的類型相同

三、改造

第一步:Mapper.xml(映射文件)

定義mapper映射文件UserMapper.xml,將UserMapper.xml放在config下mapper目錄下,效果如下:

文件內容如下:

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper

? ? ? ? PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

? ? ? ? "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- namespace:命名空間,用于隔離sql,還有一個很重要的作用,后面會講 --><mapper namespace="com.yuanqinnan.mapper.UserMapper"><select id="queryUserById" parameterType="int" resultType="com.yuanqinnan.model.User">? ? SELECT * FROM `user`where id=#{id}

? </select><!-- 查詢 user 表的所有數據--><select id="selectUserAll" resultType="com.yuanqinnan.model.User">? ? ? ? select * from user

? ? </select><!--? ? ? ? ? ? 1、${value}里面必須要寫value,不然會報錯

? ? ? ? ? ? 2、${}表示拼接 sql 字符串,將接收到的參數不加任何修飾拼接在sql語句中

? ? ? ? ? ? 3、使用${}會造成 sql 注入

? ? --><select id="selectLikeUserName" resultType="com.yuanqinnan.model.User" parameterType="String">? ? ? ? select * from user where username like '%${value}%'

? ? </select><!--#{}實現--><select id="selectLikeUserName2" resultType="com.yuanqinnan.model.User" parameterType="String">? ? ? ? select * from user where username like #{username}

? ? </select><!-- 向 user 表插入一條數據 --><insert id="insertUser" parameterType="com.yuanqinnan.model.User">? ? ? ? insert into user(id,username,sex,birthday,address)

? ? ? ? ? ? value(#{id},#{username},#{sex},#{birthday},#{address})

? ? </insert><!-- 保存用戶 --><insert id="saveUser" parameterType="com.yuanqinnan.model.User"><!-- selectKey 標簽實現主鍵返回 --><!-- keyColumn:主鍵對應的表中的哪一列 --><!-- keyProperty:主鍵對應的pojo中的哪一個屬性 --><!-- order:設置在執行insert語句前執行查詢id的sql,在執行insert語句之后執行查詢id的sql --><!-- resultType:設置返回的id的類型 --><selectKey keyColumn="id" keyProperty="id" order="AFTER"? ? ? ? ? ? ? ? ? resultType="int">? ? ? ? ? ? SELECT LAST_INSERT_ID()

? ? ? ? </selectKey>? ? ? ? INSERT INTO `user`

? ? ? ? (username,birthday,sex,address) VALUES

? ? ? ? (#{username},#{birthday},#{sex},#{address})

? ? </insert><!-- 根據 id 更新 user 表的數據 --><update id="updateUserById" parameterType="com.yuanqinnan.model.User">? ? ? ? update user set username=#{username} where id=#{id}

? ? </update><!-- 根據 id 刪除 user 表的數據 --><delete id="deleteUserById" parameterType="int">? ? ? ? delete from user where id=#{id}

? ? </delete></mapper>

其他地方未有改動,主要是namespace="com.yuanqinnan.mapper.UserMapper"的修改,現在我們實現這個接口

第二步:UserMapper(接口文件)

新建mapper包,新增接口UserMapper

內容:

publicinterface UserMapper {

? ? //查詢用戶User queryUserById(int id);

? ? //查詢用戶列表List selectUserAll();

? ? //模糊查詢List selectLikeUserName(String username);

? ? //新增void saveUser(User user);


}

第三步:加載UserMapper.xml文件

<mappers><!-- 映射文件方式1,一個一個的配置--><mapper resource="config/sqlmap/User.xml"/><mapper resource="config/mapper/UserMapper.xml"/></mappers>

測試:

publicclass MapperTest {

? ? private SqlSessionFactory sqlSessionFactory;

? ? @Before

? ? publicvoidinit()throws Exception {

? ? ? ? // 創建SqlSessionFactoryBuilderSqlSessionFactoryBuilder sqlSessionFactoryBuilder =new SqlSessionFactoryBuilder();

? ? ? ? // 加載SqlMapConfig.xml配置文件InputStream inputStream = Resources.getResourceAsStream("config/SqlMapConfig.xml");

? ? ? ? // 創建SqlsessionFactorythis.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

? ? }

? ? @Test

? ? publicvoid testQueryUserById() {

? ? ? ? // 獲取sqlSession,和spring整合后由spring管理SqlSession sqlSession =this.sqlSessionFactory.openSession();

? ? ? ? // 從sqlSession中獲取Mapper接口的代理對象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

? ? ? ? // 執行查詢方法User user = userMapper.queryUserById(1);

? ? ? ? System.out.println(user);

? ? ? ? // 和spring整合后由spring管理? ? ? ? sqlSession.close();

? ? }

? ? @Test

? ? publicvoid testQueryUserByUsername() {

? ? ? ? // 獲取sqlSession,和spring整合后由spring管理SqlSession sqlSession =this.sqlSessionFactory.openSession();

? ? ? ? // 從sqlSession中獲取Mapper接口的代理對象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

? ? ? ? // 執行查詢方法List list = userMapper.selectLikeUserName("張");

? ? ? ? for (User user : list) {

? ? ? ? ? ? System.out.println(user);

? ? ? ? }

? ? ? ? // 和spring整合后由spring管理? ? ? ? sqlSession.close();

? ? }

? ? @Test

? ? publicvoid testSaveUser() {

? ? ? ? // 獲取sqlSession,和spring整合后由spring管理SqlSession sqlSession =this.sqlSessionFactory.openSession();

? ? ? ? // 從sqlSession中獲取Mapper接口的代理對象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

? ? ? ? // 創建保存對象User user =new User();

? ? ? ? user.setUsername("劉備");

? ? ? ? user.setBirthday(new Date());

? ? ? ? user.setSex("1");

? ? ? ? user.setAddress("蜀國");

? ? ? ? // 執行查詢方法? ? ? ? userMapper.saveUser(user);

? ? ? ? System.out.println(user);

? ? ? ? // 和spring整合后由spring管理? ? ? ? sqlSession.commit();

? ? ? ? sqlSession.close();

? ? }

}

測試結果與上一篇相同

四、總結

selectOne和selectList

動態代理對象調用sqlSession.selectOne()和sqlSession.selectList()是根據mapper接口方法的返回值決定,如果返回list則調用selectList方法,如果返回單個對象則調用selectOne方法。

namespace

mybatis官方推薦使用mapper代理方法開發mapper接口,程序員不用編寫mapper接口實現類,使用mapper代理方法時,輸入參數可以使用pojo包裝對象或map對象,保證dao的通用性。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容

  • Mybatis介紹 MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache...
    day_Sunny閱讀 2,687評論 0 6
  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優秀的...
    笨鳥慢飛閱讀 5,571評論 0 4
  • 1.1mybatis下載 mybaits 的代碼由github.com 管理,地址:https://github....
    暖熊熊閱讀 875評論 0 5
  • 天???氣???太???熱,文???字???都???出???汗???了??? 熱???瘋???了,全???身???...
    我也是最懶啦閱讀 188評論 0 0
  • 本周可謂處于 “近乎中暑”的狀態。炎熱的天氣令人些許煩躁,當然還是個人修養欠缺吧。坐得令人后背疼痛的排練以及去外地...
    梁夢婷閱讀 241評論 0 1