作爲一名java開發工程師,對我而言,最簡單的瞭解技術發展趨勢的方法是沒事兒多看看招聘需求。
畢業後做了幾年開發,到了需要記筆記,寫博客的時候了,因爲總結對於做技術的真的很重要;所以看了看招聘需求,並在網上查了查一些熱門的面試題,並結合了自身的面試經歷,做了一些對於學習mybatis要點的總結。
企業要求:
對mybatis有深入的應用和優化經驗,掌握它的原理機制,有框架開發或重構經驗者優先考慮。(這應該就是所謂精通)
面試常問的技術點:
什麼是orm,說說你對mybatis的理解?
在關係型數據庫中,將表與java對象做了一個映射,通過操作java對象來實現對錶的操作,使java開發者更加專注於java代碼與流程的開發,更貼近面向對象的開發思想。而mybatis是一個半自動的orm框架,內部對jdbc進行了多層的封裝與擴展,通過xml或者註解將接口與sql進行關聯與定位,所以需要開發者編寫原生sql,並且靈活度更高,更適合敏捷開發與產品的快速迭代。
jdbc的缺點是什麼,mybatis是如何解決mybatis缺點的?
jdbc需要手動創建和關閉數據庫的連接,手動解析結果集,幾乎全都需要手動處理,冗餘代碼極多;mybatis通過xml映射,使開發者關注於接口的設計與sql的編寫,至於數據庫的驅動和連接的創建銷燬以及連接池的應用,都交給框架自己完成。
有哪些動態sql標籤,動態sql的原理是什麼?
mybatis提供了9種動態標籤:trim,where,set,foreach,if,choose,when,otherwise,bind;
通過這些標籤可以使編寫的sql可以做一些簡單的判斷,本質上是一種sql的拼接。
模糊查詢 like 語句該怎麼寫?
將%寫在java程序的參數中參數上,然後xml文件中使用#{}做sql拼接;
固定寫法,寫在xml中:%${value}%。
#{}和${}的區別是什麼?
看運行日誌文件可以發現:
#代表preparestatement,生成?佔位符;
$代表statement,傳遞的就是參數,拼接的sql;
說說mybatis的接口綁定?
將接口與sql進行綁定,使用的時候,只要調用接口的方法就可以了;
可以在方法上使用select,update等註解,使用起來比較方便,但適合表簡單,業務簡單的情況;
也可以使用xml配置的方式,dao的xml配置文件要與dao文件在同一個目錄,而且xml文件中要使用<mapper namespace="">來指定dao文件,id要對應接口的方法名,適用於sql複雜的情況。
dao接口的工作原理是什麼,裏面的方法可以重載嗎?
不能重載,因爲是根據全類名+方法名進行sql定位的,方法重載會使xml出現判斷錯誤;
dao的工作原理是jdk的動態代理,sqlSession通過getMapper()方法生成接口的代理對象,代理對象裏的方法使用sqlsession裏通過全類名+方法名和方法定位到xml中的sql語句,根據xml的select,update標籤,判斷使用jdbc裏的execute方法執行。
插入數據時,如何獲取自動生成的id值?
原理:在執行insert後,執行一個select last_insert()語句;
<insert><selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"></></>;
怎樣才能讓接口中的方法傳遞多個參數?
1.接口方法中直接傳,在xml中使用#{0},#{1},#{2}來代表參數的下標;
2.接口中使用@param註解,然後在xml中用#{}來正常表示;
3.封裝成一個map;
如果實體類屬性與sql的字段名不同,有哪些解決方式?
1.編寫sql時,查詢的字段使用別名;
2.<resultMap>標籤做映射;
3.sql查詢的結果集爲設置爲map,然後在java中設置值;
4.當使用註解時,可以使用@Results和@Result標籤設置對應關係;
5.設置Configuration對象的setMapUnderscoreToCamelCase方法:當屬性遵循駝峯命名法並且字段使用下劃線,通過修改配置可以做到屬性的自動映射;
mybatis都有哪些Executor執行器?它們之間的區別是什麼?
mybatis有三種基本的Executor執行器,SimpleExecutor、ReuseExecutor、BatchExecutor;
SimpleExecutor:每執行一次update或select,就開啓一個statement對象,用完立刻關閉statement對象;
ReuseExecutor:執行update或select,以sql作爲key查找statement對象,存在就使用,不存在就創建,用完後,不關閉statement對象,而是放置於Map<String, Statement>內,供下一次使用。簡言之,就是重複使用statement對象;
BatchExecutor:執行update(沒有select,JDBC批處理不支持select),將所有sql都添加到批處理中(addBatch()),等待統一執行(executeBatch()),它緩存了多個statement對象,每個statement對象都是addBatch()完畢後,等待逐一執行executeBatch()批處理。與JDBC批處理相同;
Executor的這些特點,都嚴格限制在sqlSession生命週期範圍內,可以在xml中配置sqlsession的ExecutorType。
如何批量插入,能返回生成的主鍵列表嗎?
能返回,連jdbc都能;
1.for循環insert
2.sqlsession設置ExecutorType.BATCH,然後正常使用for循環insert
3.for循環生成一個list,然後調用insertBatch(),在xml<insert><foreach collection ="list" item="對象" separator =","></></>
實現一對多有哪幾種方式,實現一對一又有哪幾種方式?
一對一:
從表包含主表的實體對象的引用,在<resultMap>中設置association;
默認是立即加載;
一對多:
主表設置一個從表的list屬性,然後在<resultMap>中設置collection;
一般設置爲延遲加載,原理是用cglib生成結果的代理對象,然後當調用代理對象的list屬性時,判斷代理對象的list是否爲null,如果爲null就查詢list集合,延遲加載的屬性爲lazyLoadingEnabled=true
瞭解mybatis的緩存機制嗎?
一級緩存:
sqlsession的緩存,存入的是對象
連續兩次查詢,結果爲同一個對象,因爲只請求了一次數據庫,將查詢結果存入到sqlsession的map區域中,查詢時先查詢緩存
清空緩存的方法:sqlsession.clearCache()
當調用了sqlsession的刪除修改添加,close,commit等方法,自動刪除緩存
二級緩存:
sqlFactory的緩存,存的是類似json的數據,不是對象
創建新對象,將數據寫進對象中,所以對象要實現序列化接口
由同一個sqlsessionfactory創建的sqlsession對象共享