亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

通過自動回復機器人學Mybatis---加強版

難度中級
時長 2小時43分
學習人數
綜合評分9.77
214人評價 查看評價
9.9 內容實用
9.7 簡潔易懂
9.7 邏輯清晰
  • 攔截器實現分頁3

    需要從被攔截的對象中獲取原始的sql語句和配置參數。攔截器類實現的intercept方法參數中的Invocation對象中就有被攔截下來的對象(也就是實現了StatementHandler接口的對象,由于攔截的對象有很多種,但是攔截下來的對象是確定的StatementHandler,所以這里通過getTarget()方法獲得的對象需強轉為StatementHandler類型)。

    https://img1.sycdn.imooc.com//5d4c09df0001ea7c10560263.jpg

    Mybatis的Plugin類提供的wrap()方法,攔截的如果不是需要的對象

    ,該方法返回的是原對象本身,從這以后該對象就和分頁攔截器沒有關系了。如果攔截的是需要的對象,則會返回代理類,并執行intercept方法

    查看全部
  • 攔截器實現分頁2

    使用攔截器實現分頁的前提需要有一個執行查詢的方法,這里在serviceImpl中就不再調用查詢所有記錄的方法了(原來調用查詢所有是要計算出Page的其他屬性),這里只是把Page參數傳入到Dao中,在配置文件sql中定義的查詢是查詢所有的記錄并沒有實現分頁功能的。無論是自己實現還是攔截器實現分頁都需要傳入Page對象到配置文件sql中。

    定義攔截器:攔截器根據功能的不同,可以不止一個,創建攔截器的包。

    在該包下創建攔截器類,命名為PageInterceptor,Mybatis提供了攔截的操作,可以實現分頁的功能,所以要實現Mybatis的接口Interceptor(該接口是org.apache.ibatis.plugin.Interceptor包下的)。

    https://img1.sycdn.imooc.com//5d4bcb330001650f08550155.jpg


    首先該攔截器需要對Mybatis的xml文件中執行的指定的sql語句進行攔截,并轉換為分頁的sql語句(攔截的時間是在獲得PreparedStatement對象之前,攔截的地點是在Mybatis源碼中)。

    Mybatis獲取PreparedStatement對象是在StatementHandler接口(org.apache.ibatis.executor.statement)中,該接口中的prepare方法返回的是Statement對象。

    https://img1.sycdn.imooc.com//5d4bcdef0001b44d07490260.jpg

    該接口的實現類有兩個(BaseStatementHandler、RoutingStatementHandler),該接口的實現類是BaseStatementHandler中,statement是通過該方法中的instantiateStatement(connection)獲取到的。

    https://img1.sycdn.imooc.com//5d4bceb20001f94208300251.jpginstantiateStatement方法是一個抽象方法(BaseStatementHandler接口也有三個實現類CallableStatementHandler、PreparedStatementHandler、SimpleStatementHandler),該方法是在PreparedStatementHandler實現類中實現的,如下圖就和JDBC中相似了,攔截器的攔截位置就是在這里。

    https://img1.sycdn.imooc.com//5d4bcfae0001471a10970536.jpg

    攔截器是通過Mybatis提供的注解來攔截到該位置:也就是在攔截器類的上添加@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class})}),type指的是攔截接口的class,method指向攔截的方法。args指的是攔截方法中需要傳入參數的類類型。

    https://img1.sycdn.imooc.com//5d4bd448000171e512870647.jpg

    這樣該類對應的實現代碼,在執行sql語句之前就可對源碼的功能進行修改,因為該實現代碼在執行之前已經獲取到sql語句,該實現代碼就會修改該sql語句并返回給Mybatis。

    https://img1.sycdn.imooc.com//5d4bd5010001a26910840316.jpg


    攔截器類實現的接口需要實現三個方法:

    plugin方法需要傳入一個Object參數,如果該對象符合攔截的規則(規則就是攔截器類上的注解信息),就會返回一個代理,該代理就可以使用分頁的功能,這個代理通過Plugin.wrap(Object對象,this)方法返回,this指的是當前攔截器實例。

    https://img1.sycdn.imooc.com//5d4bd61e00017ab206330211.jpg可以通過查看wrap方法的源碼,它是由Mybatis實現的,該方法調用getSignatureMap(攔截器實例)

    https://img1.sycdn.imooc.com//5d4bd6af00018a0c10980520.jpggetSignatureMap(Interceptor interceptor)方法通過攔截器實例獲取到攔截器類上寫的注解的信息(該注解的作用在于就在于這里),通過這個注解就可以找到攔截的類型

    https://img1.sycdn.imooc.com//5d4bd70d0001ef2611300522.jpg如果傳入的對象符合了攔截器的規則,就會執行攔截器的功能,修改相應的sql語句。通過interceptor(Invocation invocation)方法。如果不符合規則就不會執行interceptor方法,因為沒有獲取到代理類。

    https://img1.sycdn.imooc.com//5d4bd8410001459f10610324.jpg

    查看全部
  • 攔截器實現分頁

    實際開發中,會有很多查詢列表頁面需要分頁功能,這時分頁的簡單實現就不再適用,這時就需要把分頁功能的共通代碼分離出來,以供其他需要分頁的地方使用。

    【1】頁面的jsp和js方法的封裝(完成跳轉到后臺)

    https://img4.sycdn.imooc.com/5d4b796500015dda08560395.jpg

    【2】sql的xml文件的sql語句進行封裝(因為要傳入Limit的參數,這里定義了兩條幾乎同樣的sql語句,只不過是一條通過count(*)返回所有記錄數,這里需要把查詢所有sql語句封裝)

    【3】配置文件sql語句后的Limit和起始位置和返回數量的封裝

    https://img1.sycdn.imooc.com/5d4b799b00014cb806650157.jpg

    【4】頁面可以通過自定義標簽來解決,這樣每個需要分頁的地方直接引入該標簽即可。

    https://img3.sycdn.imooc.com/5d4b797d00019d5408740414.jpg


    原始的JDBC中Dao層的封裝:

    開發一個共通的方法,得到Connection對象,得到查詢的sql語句,該共通方法可以根據sql語句查詢出總條數(該sql語句無需截斷再拼接count(*),這樣容易出錯??梢园言搒ql語句當作子查詢,外面再嵌套一層sql語句),這樣Page的屬性就都有值了,就可以再Dao的sql語句后拼接Limit參數了。

    Mybatis中Dao層的封裝:

    該封裝的關鍵是sql語句在配置文件里,配置文件貌似獲取不到sql參數。

    Mybatis攔截器:Mybatis攔截器提供為所有頁面實現分頁的功能,對攔截到的都會實現分頁功能(實現原理:就是攔截查詢的sql語句并把它修改為分頁查詢的sql語句)。

    在沒有使用攔截器時,在執行sql之前攔截,并調用分頁共通,修改的是Mybatis的源碼。所以提供了攔截器,在不改變Mybatis源碼的同時,可以修改源碼的行為。

    Mybatis執行sql語句簡化版的過程:它的原理和JDBC相似,根據sql語句得到PreparedStatement對象,為該對象setObject,再執行execute方法,最后得到結果,Mybatis攔截器就是相當于在傳入sql語句獲得PreparedStatement對象前,修改它為分頁的sql語句。

    查看全部
  • Mybatis 的特點

    1)SQL語句與代碼分離

    優點:便于管理和維護
    缺點:不便于調試,需要借助日志工具獲得信息

    2)用標簽控制動態SQL的拼接
    優點:用標簽代替編寫邏輯代碼
    缺點:拼接復雜SQL語句時,沒有代碼靈活,比較復雜

    3)結果集與Java對象的自動映射
    優點:保證名稱相同即可自動映射
    缺點:對開發人員所寫的SQL依賴性很強

    4)編寫原生SQL(半自動)
    優點:接近JDBC,很靈活
    缺點:對SQL語句依賴程度很高,數據庫一直不方便

    查看全部
  • 分頁的簡單實現

    重點關注分頁功能中Mybatis部分的內容(觀察Mybatis的介入和之前的分頁有何不同)

    該分頁功能的參數:

    1、記錄總數。

    2、每頁顯示記錄數。

    3、總頁數。

    4、當前頁。

    5、分頁查詢Limit的起始點。

    6、分頁查詢Limit的返回個數。

    通常封裝一個類來實現分頁功能:

    Mysql使用Limit進行分頁。Limit關鍵字需要兩個參數,一個是從第幾條開始取,另一個是取多少條。

    該類中還封裝了計算總頁數的方法,并且可以計算出Limit需要的兩個參數值,然后放到該類對象里供程序使用,如下圖1,如果傳進來的當前頁數大于總頁數,就把當前頁數置為最后一頁(也可以在前端頁面進行設置,這里都在后端實現)如圖2,還需保證當前頁數不能小于1,如果小于1,則把它置為1。如圖3,最后還需要計算sql語句Limit需要的參數,如圖4。

    https://img1.sycdn.imooc.com//5d4a67c70001130208510344.jpg


    https://img1.sycdn.imooc.com//5d4a77d400011b9609150204.jpg

    https://img1.sycdn.imooc.com//5d4a78e30001d28907010206.jpg

    https://img1.sycdn.imooc.com//5d4a78e400011d1a08960210.jpg

    執行邏輯之前可以先查看Limit語句,第一頁是從第0條開始獲取,取5條。第二頁是從第5條開始取,取5條,以此類推。

    https://img1.sycdn.imooc.com//5d4a79a700011afd04620139.jpg

    分頁查詢過程:

    預先定義好當前頁面記錄數和當前頁面數,通過查詢出來的記錄數,可以計算出總頁數,Limit的參數也就獲取到了,這樣Dao層就將Page對象交給XML,XML根據這兩個參數查詢,然后將查詢的結果返回。

    Mybatis如果想傳入XML兩個參數時,可以使用Map集合。

    分頁查詢一般來說是按照某一字段進行排序,而且該字段值最好不要重復,可以是主鍵或者該字段創建的時間createTime,如果不主動設置排序方式,按照數據庫默認排序方式,并不能保證每次執行sql語句的默認排序方式都是相同的。

    前端的javascript的校驗相當于沒有校驗,所以如果考慮安全的問題時,在后端也需要加上校驗。

    https://img1.sycdn.imooc.com//5d4ad1160001ec3709780795.jpg

    https://img1.sycdn.imooc.com//5d4ad1160001c10009460701.jpg



    查看全部
  • 接口式編程原理(中)

    SqlSession接口有兩個實現類,分別為DefaultSqlSession和SqlSessionManager,這里獲取的對象是屬于DefaultSqlSession實現類的。

    首先sqlSession是我們手動封裝獲取的,這里調用的是Mybatis的方法,然后通過SqlSessionFactory對象的OpernSession方法獲取SqlSession,其中SqlSessionFactory接口也有兩個實現類,分別為DefaultSqlSessionFactory和SqlSessionManager,由源碼得知SqlSessionFactoryBuilder類提供了build(Reader reader),該方法返回的是SqlSessionFactoryBuilder類提供的build(Reader reader,String envirment,Properties properties),該方法又返回的是SqlSessionFactoryBuilder提供的build(Configuration config)方法,該方法最后返回的是DefaultSqlSessionFactory對象。所以SqlSessionFactory獲取的是DefaultSqlSessionFactory實現類對象。所以openSession方法是屬于DefaultSqlSessionFactory里的方法。該openSession方法返回的是DefaultSqlSessionFactory提供的openSessionFromDataSource(ExecutorType execType,..),該方法最終返回的是DefaultSqlSession類的對象

    所以最終獲取的是DefaultSqlSession。


    https://img3.sycdn.imooc.com/5d3e6afa00017b4706740219.jpg

    https://img4.sycdn.imooc.com/5d3e6afa0001269b07400268.jpg

    https://img1.sycdn.imooc.com/5d3e6afa0001b23710870526.jpg

    https://img1.sycdn.imooc.com/5d3e6b8c0001058a11200617.jpghttps://img4.sycdn.imooc.com/5d3e6c2900018d9d11290560.jpghttps://img2.sycdn.imooc.com/5d3e6c6b00018d9d11290560.jpg

    這里我們可以查看DefaultSqlSession的getMapper方法,該方法返回的是Configuration類提供的getMapper方法,該方法第一個參數就是傳進來的class,也就是接口的類類型,第二個參數是this,也就是方法的對象,也就是sqlSession,該方法返回的是MapperRegistry類提供的getMapper方法,該方法返回值可以理解為通過代理工廠,生產一個代理返回出去(這里就是前面說的通過動態代理創建實例)。

    https://img1.sycdn.imooc.com/5d3e6d2500010a2a11320574.jpghttps://img3.sycdn.imooc.com/5d3e6d930001ff6510690588.jpghttps://img1.sycdn.imooc.com/5d3e6ddd000180f411070615.jpg


    該動態工廠的由來是Map對象(以類類型作為Key,MapperProxyFactory作為Value)的get方法,該get方法中傳入一個類類型,MapperRegistry類提供了addMapper方法,該方法需要傳入一個類類型,然后用Map對象的input方法把傳入的類類型作為key,臨時創建一個動態工廠作為value,并傳入這個類類型,只有調用了這個方法才會對Map集合初始化,該方法的調用是在加載Mybatis核心配置文件時進行調用的,它會不停的調用這個方法,為不同的Class創建代理工廠。

    https://img1.sycdn.imooc.com//5d3e878d0001601b11490170.jpg

    https://img1.sycdn.imooc.com//5d3e878e0001728d11390142.jpg

    https://img1.sycdn.imooc.com//5d3e88440001745f11260313.jpg

    動態工廠創建代理對象是通過MapperProxyFactory的new Instance(SqlSession sqlSession)方法,該方法中創建了代理類,該代理類的構造函數中第一個參數是傳進來的sqlSession,后兩個參數是代理工廠的屬性,第二個參數就是接口的類類型,構造函數并沒有為其他屬性賦值,所以第三個參數只是Map初始化的一個對象。

    https://img1.sycdn.imooc.com//5d3e8a140001af8711350580.jpg

    https://img1.sycdn.imooc.com//5d3e8ac40001f60311100309.jpg

    查看全部
  • 接口式編程原理

    講解接口式原理之前需了解如下幾個問題

    https://img2.sycdn.imooc.com/5d3925440001225e10590498.jpg

    問題1:沒有實現類的接口為甚么可以實現方法的功能(答案:是通過動態代理。簡單的動態代理過程,是要有一個實現InvocationHandler接口的類,這里給這個類起名為MapperProxy,因為Mybatis源碼中就是起的這個名稱,這個類必須實現invoke()方法。然后用這個類通過Proxy.newProxyInstance(類加載器,接口,MapperProxy對象)創建一個代理實例,在案例中是通過sqlSession.getMapper()獲取到代理實例的,表面上看是使用接口承接的,但該對象不是實現類的對象,而是一個代理實例,然后是通過這個代理實例調用接口里的方法,由動態代理知識,它并不會執行這個方法,而是會觸發MapperProxy的invoke()方法,這樣沒有實現類的接口方法就可以執行了)。

    https://img3.sycdn.imooc.com/5d3922320001931d11580680.jpg


    問題2:雖然調用接口方法時,走的是invoke()方法,怎么知道調用的sql語句是什么樣子的呢?(因為調用的sql語句在配置文件中,在獲取SqlSession對象之前,由于調用加載Mybatis核心配置文件的方法,Mybatis配置文件中引入了sql配置文件的路徑,這樣加載Mybatis總配置文件的同時,也把其他配置文件加載了,這些信息Mybatis會存儲到對象(Configuration)中,當代理實例調用接口方法時,如果該接口方法與配置信息能對應上(配置文件的namespace等于包名+接口名,方法名等于id名,接口參數等于parameterType,返回值類型等于resultType),就可以成功調用,根據上節課知識,這里是存在某種聯系的——>接口的全名稱就是配置文件的namespace,調用的方法名就是定義sql標簽的id,接口的全名稱和調用的方法名在invoke()方法中是可以獲取到的,有了這些信息就可以獲取到配置文件信息,然后再invoke方法里就可以代替原來寫的方法)

    https://img2.sycdn.imooc.com/5d3924af0001bafb09370631.jpg

    問題3:根據動態代理的知識,Proxy.newProxyInstance()返回的是Object類型的對象,但卻賦值給接口類型的對象?

    (答案:這里是泛型的作用,當使用getMapper()傳入的是什么樣的類類型,就可以使用什么樣的類型去接值,這就是Mybatis利用泛型進行強轉了)。

    https://img2.sycdn.imooc.com/5d3e63220001016211360630.jpg

    查看全部
  • 接口式編程(針對調用配置文件sql語句這行代碼,有四處值得分析的地方)

    1、namespace :方法里的namespace需要和mapper標簽的namespace一致,由于兩邊是手寫的,可能存在不一致的風險,而且也不能保證多個sql配置文件,namespace不沖突。

    ?2、與sql關聯的id :方法里的id和標簽的id也是手寫的,也存在不一致的風險。

    ?3、傳入的參數 :例如selectList傳入的參數類型是Object,所以傳入的參數不管是何種類型,它不會報錯,但是如果傳入的類型和parameterType類型不匹配,sql語句中引用的參數就會出錯。

    ?4、返回值:例如selectList方法,Mybatis提供了一種約束,只要是List即可,無論集合中存儲何種類型,但是這樣不意味執行就是對的,因為真正存入的是resultMap約束的,編譯時不會報錯,執行時可能就會報錯。

    SqlSession方法的mapper的namespace、與sql關聯的id、傳入的參數、返回值。

    接口式編程:就是為了避免上述風險,而人為做的強制性規范和約束,Mybatis提供的這種方式,就稱作接口式編程(相當于sql的配置文件有一個java接口作為代言人,這樣SqlSession對象直接調用接口里的方法即可。但是該接口有一些前提:

    1、namespace的統一:該接口的包名+接口名就是namespace名。

    2、sql標簽id的統一:代言人代言一條sql語句提供給外面,代言哪條sql語句,就提供和該sql的id相同名稱方法。該接口可以代言sql配置文件的sql語句,通過提供方法,方法名為id名。

    3、方法參數的統一:接口方法參數類型為parameterType類型。

    4、方法返回值的統一:接口方法返回值類型為resultMap類型。

    注意:如上該接口就可以代言sql語句了。該接口不用人為手動編寫實現類,通過Mybatis獲取該接口,就可以調用,Mybatis已經實現了該接口(它就會知道該方法是調用配置文件中的哪條sql語句)。因為當前該接口沒有實現類,這里通過SqlSession對象的getMapper(接口的類類型)就可以獲得該接口實現類的代理對象,這樣就可以直接調用接口里的方法,而不用傳入namespace+id,而是按照接口的約束進行調用)。

    這樣就避免了上述的問題:namespace不可能相同,因為不可能有多個相同名全路徑的接口,調用方法時也不需要傳入namespace。同一個接口里也不肯有多個相同名稱的方法。傳入的參數已經被限制,如果不符合編譯會報錯。返回的接口也被限定,如果不符合編譯也會報錯。

    接口式編程的作用:
    1、規范訪問配置文件

    2、當mybatis和spring整合后,配置的數據源將交給Spring管理,也就意味著認為手寫的提供SqlSession會消失,Spring將提供SqlSesssion,傳入的參數應該交給Service處理好再傳入進來。通過SqlSession調用接口式編程的這些代碼統統都由Spring來實現。這個Dao層將會消失,該接口將會變成真正的Dao層,這時Dao層將只剩下接口文件和配置文件。

    https://img4.sycdn.imooc.com/5d391bc00001803c08140440.jpg

    https://img2.sycdn.imooc.com/5d391bc20001ef2210950322.jpg

    https://img2.sycdn.imooc.com/5d391c1a0001437809360282.jpg
    當Mybatis與Spring結合時,這些Spring提供了便捷,這里只做一些了解即可,整合之后整個Dao層只剩接口文件和配置文件。


    查看全部
    1 采集 收起 來源:接口式編程

    2019-08-06

舉報

0/150
提交
取消
課程須知
本課程的前導課程為《通過自動回復機器人學 Mybatis ---基礎版》, 課程中案例的關聯性極強,所以學習本課程唯一的條件就是學習過《通過自動回復機器人學 Mybatis ---基礎版》
老師告訴你能學到什么?
1、 Mybatis 的接口式編程 2、實現分頁查詢 3、通過攔截器實現分頁共通來了解 Mybatis 的攔截器 4、通過如何用數組做參數來了解 Mybatis 對類型的處理 5、 Mybatis 如何實現 jdbc 的 addBatch ,即批量插入

微信掃碼,參與3人拼團

微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

友情提示:

您好,此課程屬于遷移課程,您已購買該課程,無需重復購買,感謝您對慕課網的支持!