Java面试——MyBatis系列总结
文章目錄:
1.MyBatis是什么?
2.JDBC編程有哪些缺陷?MyBatis又是如何改進(jìn)的?
3.MyBatis與Hibernate的區(qū)別在哪?
4.MyBatis的優(yōu)缺點(diǎn)
5.請(qǐng)說(shuō)說(shuō)MyBatis的工作原理
6.MyBatis的架構(gòu)設(shè)計(jì)是怎樣的?
7.#{}和${}的區(qū)別
8.模糊查詢like語(yǔ)句該怎么寫
9.如何獲取生成的主鍵?
10.當(dāng)實(shí)體類中的屬性名和表中的字段名不一樣怎么辦?
11.什么是MyBatis的接口綁定?有哪些實(shí)現(xiàn)方式?
12.使用MyBatis的mapper接口調(diào)用時(shí)有哪些要求?
13.最佳實(shí)踐中,通常一個(gè)Xml映射文件,都會(huì)寫一個(gè)Dao接口與之對(duì)應(yīng),請(qǐng)問,這個(gè)Dao接口的工作原理是什么?Dao接口里的方法,參數(shù)不同時(shí),方法能重載嗎
14.MyBatis動(dòng)態(tài)sql是做什么的?都有哪些動(dòng)態(tài)sql?能簡(jiǎn)述一下動(dòng)態(tài)sql的執(zhí)行原理不?
15.MyBatis的一級(jí)、二級(jí)緩存是什么?
1.MyBatis是什么?
MyBatis是一款優(yōu)秀的dao持久層框架、一個(gè)半ORM(對(duì)象關(guān)系映射)框架。它支持定制化SQL、存儲(chǔ)過程、高級(jí)映射、緩存機(jī)制,同時(shí)MyBatis幾乎避免了JDBC代碼中手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集等繁雜操作的過程。
2.JDBC編程有哪些缺陷?MyBatis又是如何改進(jìn)的?
- JDBC編程中頻繁創(chuàng)建、釋放數(shù)據(jù)庫(kù)連接對(duì)象,容易造成系統(tǒng)資源浪費(fèi),影響系統(tǒng)性能。可以使用連接池解決這個(gè)問題。
? 解決:在mybatis-config.xml中配置數(shù)據(jù)庫(kù)連接池,使用連接池管理數(shù)據(jù)庫(kù)連接。
- JDBC編程中 sql 語(yǔ)句寫在代碼中造成代碼不易維護(hù),實(shí)際應(yīng)用場(chǎng)景中sql的變化可能較大,sql變動(dòng)需要改變java代碼。
? 解決:將SQL語(yǔ)句配置在XXXXmapper.xml映射文件中,與java代碼分離。
- JDBC編程中向sql語(yǔ)句傳參數(shù)麻煩,因?yàn)閟ql語(yǔ)句的where條件不一定,可能多也可能少,占位符需要和參數(shù)一一對(duì)應(yīng)。
? 解決:Mybatis中自動(dòng)將java對(duì)象映射至sql語(yǔ)句。
- JDBC編程中對(duì)結(jié)果集解析麻煩,sql變化導(dǎo)致解析代碼變化,且解析前需要遍歷,如果能將數(shù)據(jù)庫(kù)記錄封裝成pojo對(duì)象解析比較方便。
? 解決:Mybatis中自動(dòng)將sql執(zhí)行結(jié)果映射至java對(duì)象。
3.MyBatis與Hibernate的區(qū)別在哪?
首先要提到一個(gè)詞ORM。ORM(Object Relational Mapping)對(duì)象關(guān)系映射,是一種為了解決關(guān)系型數(shù)據(jù)庫(kù)數(shù)據(jù)與簡(jiǎn)單Java對(duì)象(POJO)的映射關(guān)系的技術(shù)。
相同點(diǎn):
- 都是對(duì)jdbc的封裝,都是持久層的框架,都用于dao層的開發(fā)。
不同點(diǎn):
- Hibernate是全自動(dòng)ORM映射工具,Hibernate 對(duì)SQL語(yǔ)句封裝,提供了日志、緩存、級(jí)聯(lián)(級(jí)聯(lián)比 MyBatis 強(qiáng)大)等特性,此外還提供 HQL(Hibernate Query Language)操作數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)無(wú)關(guān)性支持好,但會(huì)多消耗性能。使用Hibernate查詢關(guān)聯(lián)對(duì)象或者關(guān)聯(lián)集合對(duì)象時(shí),可以根據(jù)對(duì)象關(guān)系模型直接獲取,所以它是全自動(dòng)的。
- MyBatis 在查詢關(guān)聯(lián)對(duì)象或關(guān)聯(lián)集合對(duì)象時(shí),需要手動(dòng)編寫 SQL,支持動(dòng)態(tài) SQL、處理列表、動(dòng)態(tài)生成表名、支持存儲(chǔ)過程。所以,稱之為半自動(dòng)ORM映射工具。
4.MyBatis的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
與傳統(tǒng)的數(shù)據(jù)庫(kù)訪問技術(shù)相比,ORM有以下優(yōu)點(diǎn):
- 基于SQL語(yǔ)句編程,相當(dāng)靈活,不會(huì)對(duì)應(yīng)用程序或者數(shù)據(jù)庫(kù)的現(xiàn)有設(shè)計(jì)造成任何影響,SQL寫在XML里,解除SQL與程序代碼的耦合,便于統(tǒng)一管理;提供XML標(biāo)簽,支持編寫動(dòng)態(tài)SQL語(yǔ)句,并可重用。
- 與JDBC相比,減少了50%以上的代碼量,消除了JDBC大量冗余的代碼,不需要手動(dòng)開關(guān)連接。
- 很好的與各種數(shù)據(jù)庫(kù)兼容(因?yàn)镸yBatis使用JDBC來(lái)連接數(shù)據(jù)庫(kù),所以只要JDBC支持的數(shù)據(jù)庫(kù)MyBatis都支持)。
- 提供映射標(biāo)簽,支持對(duì)象與數(shù)據(jù)庫(kù)的字段映射;提供對(duì)象關(guān)系映射標(biāo)簽,支持對(duì)象關(guān)系組件維護(hù)。
- 能夠與Spring很好的集成。
缺點(diǎn)
- SQL語(yǔ)句的編寫工作量較大,尤其當(dāng)字段多、關(guān)聯(lián)表多時(shí),對(duì)開發(fā)人員編寫SQL語(yǔ)句的功底有一定要求。
- SQL語(yǔ)句依賴于數(shù)據(jù)庫(kù),導(dǎo)致數(shù)據(jù)庫(kù)移植性差,不能隨意更換數(shù)據(jù)庫(kù)。
5.請(qǐng)說(shuō)說(shuō)MyBatis的工作原理
通過加載mybatis全局配置文件以及mapper映射文件初始化configuration對(duì)象和Executor對(duì)象(通過全局配置文件中的defaultExecutorType初始化);
創(chuàng)建一個(gè)defaultSqlSession對(duì)象,將configuration對(duì)象和Executor對(duì)象注入給defaulSqlSession對(duì)象中;
defaulSqlSession通過getMapper()獲取mapper接口的代理對(duì)象mapperProxy(mapperProxy中包含defaultSQLSession對(duì)象)
執(zhí)行增刪改查:
- 通過defaulSqlSession中的屬性Executor創(chuàng)建statementHandler對(duì)象;
- 創(chuàng)建statementHandler對(duì)象的同時(shí)也創(chuàng)建parameterHandler和resultSetHandler;
通過parameterHandler設(shè)置預(yù)編譯參數(shù)及參數(shù)值;
調(diào)用statementHandler執(zhí)行增刪改查;
通過resultsetHandler封裝查詢結(jié)果。
6.MyBatis的架構(gòu)設(shè)計(jì)是怎樣的?
- API接口層:提供給外部使用的接口API,開發(fā)人員通過這些本地API來(lái)操縱數(shù)據(jù)庫(kù)。接口層一接收到調(diào)用請(qǐng)求就會(huì)調(diào)用數(shù)據(jù)處理層來(lái)完成具體的數(shù)據(jù)處理。
- 數(shù)據(jù)處理層:負(fù)責(zé)具體的SQL查找、SQL解析、SQL執(zhí)行和執(zhí)行結(jié)果映射處理等。它主要的目的是根據(jù)調(diào)用的請(qǐng)求完成一次數(shù)據(jù)庫(kù)操作。
- 基礎(chǔ)支撐層:負(fù)責(zé)最基礎(chǔ)的功能支撐,包括連接管理、事務(wù)管理、配置加載和緩存處理,這些都是共用的東西,將他們抽取出來(lái)作為最基礎(chǔ)的組件。為上層的數(shù)據(jù)處理層提供最基礎(chǔ)的支撐。
- 引導(dǎo)層:加載xml配置和Java配置。
7.#{}和${}的區(qū)別
- #{}是占位符,預(yù)編譯處理,可以防止SQL注入;${}是拼接符,字符串替換,沒有預(yù)編譯處理,不能防止SQL注入。
- Mybatis在處理#{}時(shí),#{}傳入?yún)?shù)是以字符串傳入,會(huì)將SQL中的#{}替換為?號(hào),調(diào)用PreparedStatement的set方法來(lái)賦值;Mybatis在處理時(shí),是原值傳入,就是把{}時(shí),是原值傳入,就是把時(shí),是原值傳入,就是把{}替換成變量的值,相當(dāng)于JDBC中的Statement編譯。
- #{} 的變量替換是在DBMS 中,變量替換后,#{} 對(duì)應(yīng)的變量自動(dòng)加上單引號(hào);的變量替換是在DBMS外,變量替換后,{} 的變量替換是在 DBMS 外,變量替換后,的變量替換是在DBMS外,變量替換后,{} 對(duì)應(yīng)的變量不會(huì)加上單引號(hào)。
8.模糊查詢like語(yǔ)句該怎么寫
- “%”#{question}"%" 注意:因?yàn)?{…}解析成sql語(yǔ)句時(shí)候,會(huì)在變量外側(cè)自動(dòng)加單引號(hào)’ ',所以這里 % 需要使用雙引號(hào)" ",不能使用單引號(hào) ’ ',不然會(huì)查不到任何結(jié)果。
- ‘%${question}%’ 可能引起SQL注入,不推薦。
- CONCAT(’%’,#{question},’%’) 使用CONCAT()函數(shù),推薦。
- 使用bind標(biāo)簽。
9.如何獲取生成的主鍵?
對(duì)于支持主鍵自增的數(shù)據(jù)庫(kù)(MySQL)
<!-- useGeneratedKeys 設(shè)置為"true"表明 MyBatis 要獲取由數(shù)據(jù)庫(kù)自動(dòng)生成的主鍵,keyColumn指定數(shù)據(jù)庫(kù)主鍵,keyProperty指定 Java 實(shí)體類中對(duì)應(yīng)的主鍵字段 --> <insert id="insertUser" useGeneratedKeys="true" >keyProperty="userId" >insert into user(user_name, user_password, create_time)values(#{userName}, #{userPassword} , #{createTime, jdbcType= TIMESTAMP}) </insert>parameterType 可以不寫,Mybatis可以推斷出傳入的數(shù)據(jù)類型。如果想要訪問主鍵,那么parameterType 應(yīng)當(dāng)是java實(shí)體或者M(jìn)ap。這樣數(shù)據(jù)在插入之后可以通過java實(shí)體或者M(jìn)ap來(lái)獲取主鍵值。
10.當(dāng)實(shí)體類中的屬性名和表中的字段名不一樣怎么辦?
第1種:通過在查詢的SQL語(yǔ)句中定義字段名的別名,讓字段名的別名和實(shí)體類的屬性名一致。
<select id="getEmpById" resultType="com.szh.bean.Employee">select id,last_name lastName,email,genderfrom employeewhere id = #{id} </select>第2種:通過<resultMap>來(lái)映射字段名和實(shí)體類屬性名的一一對(duì)應(yīng)關(guān)系。
<resultMap id="myMap" type="com.szh.bean.Employee"><id column="id" property="id"/><result column="last_name" property="lastName"/><result column="email" property="email"/><result column="gender" property="gender"/> </resultMap>第3種:在mybatis全局配置文件中開啟駝峰命名規(guī)則。
<settings><setting name="mapUnderscoreToCamelCase" value="true"/> </settings>11.什么是MyBatis的接口綁定?有哪些實(shí)現(xiàn)方式?
接口綁定,就是在MyBatis中任意定義接口,然后把接口里面的方法和SQL語(yǔ)句綁定,我們調(diào)用接口方法的時(shí)候,最終會(huì)執(zhí)行綁定的SQL語(yǔ)句。
接口綁定有兩種實(shí)現(xiàn)方式,當(dāng)Sql語(yǔ)句比較簡(jiǎn)單時(shí)候,可以使用注解綁定,當(dāng)SQL語(yǔ)句比較復(fù)雜時(shí)候,一般用xml綁定的比較多。
- 通過注解綁定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql語(yǔ)句來(lái)實(shí)現(xiàn)接口綁定;
- 通過在xml里面寫SQL語(yǔ)句來(lái)實(shí)現(xiàn)綁定, 在這種情況下,要指定xml映射文件里面的namespace必須為接口的全限定類名,同時(shí)接口的方法名和SQL語(yǔ)句的id一一對(duì)應(yīng)。
12.使用MyBatis的mapper接口調(diào)用時(shí)有哪些要求?
- Mapper.xml文件中的namespace應(yīng)該是對(duì)應(yīng)mapper接口的全限定類名。
- Mapper接口方法名和mapper.xml中定義的sql語(yǔ)句id一一對(duì)應(yīng)。
- Mapper接口方法的輸入?yún)?shù)類型和mapper.xml中定義的每個(gè)sql語(yǔ)句的parameterType的類型相同。
- Mapper接口方法的輸出參數(shù)類型和mapper.xml中定義的每個(gè)sql語(yǔ)句的resultType的類型相同。
13.最佳實(shí)踐中,通常一個(gè)Xml映射文件,都會(huì)寫一個(gè)Dao接口與之對(duì)應(yīng),請(qǐng)問,這個(gè)Dao接口的工作原理是什么?Dao接口里的方法,參數(shù)不同時(shí),方法能重載嗎
Dao接口,就是人們常說(shuō)的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法內(nèi)的參數(shù),就是傳遞給sql的參數(shù)。Mapper接口是沒有實(shí)現(xiàn)類的,當(dāng)調(diào)用接口方法時(shí),接口全限名+方法名拼接字符串作為key值,可唯一定位一個(gè)MappedStatement
舉例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace為com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一個(gè)<select>、<insert>、<update>、<delete>標(biāo)簽,都會(huì)被解析為一個(gè)MappedStatement對(duì)象。
Dao接口里的方法,是不能重載的,因?yàn)槭侨薅惷?#43;方法名的保存和尋找策略,需要保證全限定類名+方法名的唯一性。(重載了話,方法名一定是重復(fù)的)
Dao接口的工作原理是JDK動(dòng)態(tài)代理,Mybatis運(yùn)行時(shí)會(huì)使用JDK動(dòng)態(tài)代理為Dao接口生成代理對(duì)象proxy,代理對(duì)象proxy會(huì)攔截接口方法調(diào)用,轉(zhuǎn)而執(zhí)行方法對(duì)應(yīng)的sql語(yǔ)句,然后將sql執(zhí)行結(jié)果返回。
14.MyBatis動(dòng)態(tài)sql是做什么的?都有哪些動(dòng)態(tài)sql?能簡(jiǎn)述一下動(dòng)態(tài)sql的執(zhí)行原理不?
Mybatis動(dòng)態(tài)sql可以讓我們?cè)趚ml映射文件內(nèi),以標(biāo)簽的形式編寫動(dòng)態(tài)sql,完成邏輯判斷和動(dòng)態(tài)拼接sql的功能,Mybatis提供了9種動(dòng)態(tài)sql標(biāo)簽trim|where|set|foreach|if|choose|when|otherwise|bind。
其執(zhí)行原理為,使用OGNL(對(duì)象導(dǎo)航圖語(yǔ)言O(shè)bject Graph Navigation Language)從sql參數(shù)對(duì)象中計(jì)算表達(dá)式的值,根據(jù)表達(dá)式的值動(dòng)態(tài)拼接sql,以此來(lái)完成動(dòng)態(tài)sql的功能。
15.MyBatis的一級(jí)、二級(jí)緩存是什么?
- 一級(jí)緩存:采用 PerpetualCache,HashMap 存儲(chǔ)。MyBatis默認(rèn)打開一級(jí)緩存,其存儲(chǔ)作用域?yàn)?當(dāng)前sqlSession會(huì)話對(duì)象,當(dāng) sqlSession flush 或 close 之后,該 sqlSession 中的所有 Cache 就將清空。可以調(diào)用clearCache();//手動(dòng)清理緩存。
- 二級(jí)緩存:默認(rèn)也是采用 PerpetualCache,HashMap 存儲(chǔ),不同之處在于二級(jí)緩存的存儲(chǔ)作用域?yàn)?Mapper(Namespace),并且可自定義存儲(chǔ)源,如 Ehcache。默認(rèn)不打開二級(jí)緩存,開啟二級(jí)緩存之后(在mybatis主配置文件中添加<setting name="cacheEnabled" value="true"/>;其次在對(duì)應(yīng)的mapper映射文件中添加 ),對(duì)應(yīng)的實(shí)體類需要實(shí)現(xiàn)Serializable序列化接口(可用來(lái)保存對(duì)象的狀態(tài))。
- 對(duì)于緩存數(shù)據(jù)更新機(jī)制,當(dāng)某一個(gè)作用域(一級(jí)緩存 Session/二級(jí)緩存Namespaces)進(jìn)行了C/U/D 操作后,默認(rèn)該作用域下所有緩存將被清理掉。
總結(jié)
以上是生活随笔為你收集整理的Java面试——MyBatis系列总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java joda 获取utc时间_ja
- 下一篇: java 使用.aar_java -