山西電力建設(shè)三公司網(wǎng)站免費(fèi)的行情網(wǎng)站app
一、介紹下MyBatis中的工作原理
1。介紹MyBatis的基本情況:ORM
2。原理:
- MyBatis框架的初始化操作
- 處理SQL請(qǐng)求的流程
1.系統(tǒng)啟動(dòng)的時(shí)候會(huì)加載解析全局配置文件和對(duì)應(yīng)映射文件。加載解析的相關(guān)信息存儲(chǔ)在 Configuration 對(duì)象
@Testpublic void test1() throws Exception{// 1.獲取配置文件InputStream in = Resources.getResourceAsStream("mybatis-config.xml");// 2.加載解析配置文件并獲取SqlSessionFactory對(duì)象// SqlSessionFactory 的實(shí)例我們沒有通過 DefaultSqlSessionFactory直接來(lái)獲取// 而是通過一個(gè)Builder對(duì)象來(lái)建造的// SqlSessionFactory 生產(chǎn) SqlSession 對(duì)象的 SqlSessionFactory 應(yīng)該是單例// 全局配置文件和映射文件 也只需要在 系統(tǒng)啟動(dòng)的時(shí)候完成加載操作// 通過建造者模式來(lái) 構(gòu)建復(fù)雜的對(duì)象 1.完成配置文件的加載解析 2.完成SqlSessionFactory的創(chuàng)建SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);// 3.根據(jù)SqlSessionFactory對(duì)象獲取SqlSession對(duì)象SqlSession sqlSession = factory.openSession();// 4.通過SqlSession中提供的 API方法來(lái)操作數(shù)據(jù)庫(kù)List<User> list = sqlSession.selectList("com.boge.mapper.UserMapper.selectUserList");// 獲取接口的代碼對(duì)象 得到的其實(shí)是 通過JDBC代理模式獲取的一個(gè)代理對(duì)象// UserMapper mapper = sqlSession.getMapper(UserMapper.class);//List<User> list = mapper.selectUserList();System.out.println("list.size() = " + list.size());// 5.關(guān)閉會(huì)話sqlSession.close(); // 關(guān)閉session 清空一級(jí)緩存}
SqlSessionFactory: new DefaultSqlSessionFactory 全局配置文件的加載解析【Configuration】,映射文件的加載解析【Configuration,MappedStatement】
SqlSession:new DefaultSqlSession,創(chuàng)建相關(guān)的事務(wù)工廠,完成Executor的創(chuàng)建,已經(jīng)二級(jí)緩存 CachingExecutor的裝飾,同時(shí)完成了插件邏輯的植入。
selectOne(); 二級(jí)緩存 -> 一級(jí)緩存 --> 數(shù)據(jù)庫(kù)插入
SqlSession.getMapper();
源碼結(jié)構(gòu)
二、介紹下MyBatis中的緩存設(shè)計(jì)
1。緩存的作用
緩存的作用:減低數(shù)據(jù)源的訪問頻率。從而提高數(shù)據(jù)源的處理能力?;蛘咛岣叻?wù)器的響應(yīng)速度
2。MyBatis中的緩存設(shè)計(jì)
- MyBatis中的緩存的架構(gòu)設(shè)計(jì):裝飾器模式
- MyBatis中的一級(jí)緩存和二級(jí)緩存
- 一級(jí)緩存:session級(jí)別
- 二級(jí)緩存:SqlSessionFactory級(jí)別
緩存的設(shè)計(jì)
通過裝飾模式實(shí)現(xiàn)緩存功能擴(kuò)展
緩存的應(yīng)用
一級(jí)緩存和二級(jí)緩存
一級(jí)緩存和二級(jí)緩存的順序問題:先二級(jí)緩存再一級(jí)緩存
為什么會(huì)先走二級(jí)緩存再走一級(jí)緩存?
二級(jí)緩存的作用域是SqlSessionFactory級(jí)別-90%找到
一級(jí)緩存是SqlSession級(jí)別的-5%找到
1 2
2 1
一級(jí)緩存開關(guān)
二級(jí)緩存開關(guān)
三、聊下MyBatis中如何實(shí)現(xiàn)緩存的擴(kuò)展
1??疾炷愕腗yBatis中緩存架構(gòu)的理解
2??疾炷銓?duì)MyBatis緩存的擴(kuò)展。實(shí)際動(dòng)手能力
- 創(chuàng)建Cache接口的實(shí)現(xiàn)。重新getObject和putObject方法
- 怎么讓我們自定義的實(shí)現(xiàn):在cache標(biāo)簽中通過type屬性關(guān)聯(lián)我們自定義的Cache接口的實(shí)現(xiàn)
四、MyBatis中涉及到的設(shè)計(jì)模式
1。從MyBatis的整體架構(gòu)設(shè)計(jì)來(lái)分析
基礎(chǔ)模塊:
緩存模塊:裝飾器模式
日志模塊:適配器模式【策略模式】代理模式
反射模塊:工廠模式,裝飾器模式
Mapping:代理模式
SqlSessionFactory :SqlSessionFactoryBuilder 建造者模式
模板方法模式:
五、談?wù)勀銓?duì)SqlSessionFactory的理解
SqlSessionFactory是MyBatis中非常核心的一個(gè)API。是一個(gè)SqlSessionFactory工廠。目的是創(chuàng)建SqlSession對(duì)象。SqlSessionFactory應(yīng)該是單例。SqlSessionFactory對(duì)象的創(chuàng)建是通過SqlSessionFactoryBuilder來(lái)實(shí)現(xiàn)。在SqlSessionFactoryBuilder即完成了SqlSessionFactory對(duì)象的創(chuàng)建。也完成了全局配置文件和相關(guān)的映射文件的加載和解析操作。相關(guān)的加載解析的信息會(huì)被保存在Configuration對(duì)象中。
而且涉及到了兩種涉及模式:工廠模式,建造者模式
六、談?wù)勀銓?duì)SqlSession的理解
SqlSession是MyBatis中非常核心的一個(gè)API:作用是通過相關(guān)API來(lái)實(shí)現(xiàn)對(duì)應(yīng)的數(shù)據(jù)庫(kù)數(shù)據(jù)的操作。
SqlSession對(duì)象的獲取需要通過SqlSessionFactory來(lái)實(shí)現(xiàn)。是一個(gè)會(huì)話級(jí)別的。當(dāng)一個(gè)新的會(huì)話到來(lái)的時(shí)候。我們需要新建一個(gè)SqlSession對(duì)象來(lái)處理。當(dāng)一個(gè)會(huì)話結(jié)束后我們需要關(guān)閉相關(guān)的會(huì)話資源。處理請(qǐng)求的方式:
- 通過相關(guān)的增刪改查的API直接處理
- 可以通過getMapper(xxx.class) 來(lái)獲取相關(guān)的mapper接口的代理對(duì)象來(lái)處理
七、談?wù)勀銓?duì)MyBatis的理解
MyBatis應(yīng)該是我們?cè)诠ぷ髦惺褂妙l率最高的一個(gè)ORM框架。持久層框架
- 提供非常方便的API來(lái)實(shí)現(xiàn)增刪改查操作
- 支持靈活的緩存處理方案,一級(jí)緩存、二級(jí)緩存,三級(jí)緩存
- 還支持相關(guān)的延遲數(shù)據(jù)加載的處理
- 還提供了非常多的靈活標(biāo)簽來(lái)實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)處理,if forech where trim set bind …
- 相比于Hibernate會(huì)更加的靈活
八、談?wù)凪yBatis中的分頁(yè)原理
1。談?wù)劮猪?yè)的理解:數(shù)據(jù)太多。用戶并不需要這么多。我們的內(nèi)存也放不下這么多的數(shù)據(jù)
SQL:MySQL:limitOracle:rowid
2。談?wù)凪yBatis中的分頁(yè)實(shí)現(xiàn)
在MyBatis中實(shí)現(xiàn)分頁(yè)有兩種實(shí)現(xiàn)
- 邏輯分頁(yè):RowBounds
- 物理分頁(yè):攔截器實(shí)現(xiàn)
九、Spring中是如何解決DefaultSqlSession的數(shù)據(jù)安全問題的
DefaultSqlSession是線程非安全的。也就意味著我們不能夠把DefaultSqlSession聲明在成員變量中。
在Spring中提供了一個(gè)SqlSessionTemplate來(lái)實(shí)現(xiàn)SqlSession的相關(guān)的定義。然后在SqlSessionTemplate中的每個(gè)方法都通過SqlSessionProxy來(lái)操作。這個(gè)是一個(gè)動(dòng)態(tài)代理對(duì)象。然后在動(dòng)態(tài)代理對(duì)象中通過方法級(jí)別的DefaultSqlSession來(lái)實(shí)現(xiàn)相關(guān)的數(shù)據(jù)庫(kù)的操作
十、談?wù)勀銓?duì)MyBatis中的延遲加載的理解
延遲加載:等一會(huì)加載。在多表關(guān)聯(lián)查詢操作的時(shí)候可以使用到的一種方案。如果是單表操作就完全沒有延遲加載的概念。比如。查詢用戶和部門信息。如果我們僅僅只是需要用戶的信息。而不需要用戶對(duì)應(yīng)的部門信息。這時(shí)就可以使用延遲加載機(jī)制來(lái)處理。
1。需要開啟延遲加載
2。需要配置多表關(guān)聯(lián)
- association 一對(duì)一的關(guān)聯(lián)配置
- collection 一對(duì)多的關(guān)聯(lián)配置
延遲加載的原理:代理對(duì)象
十一、談?wù)剬?duì)MyBatis中插件的原理理解
MyBatis中的插件設(shè)計(jì)的目的是什么:方便我們開發(fā)人員實(shí)現(xiàn)對(duì)MyBatis功能的增強(qiáng)
設(shè)計(jì)中允許我們對(duì):
- Executor
- ParameterHandler
- ResultSetHandler
- StatementHandler
這四個(gè)對(duì)象的相關(guān)方法實(shí)現(xiàn)增強(qiáng)
要實(shí)現(xiàn)自定義的攔截器:
- 創(chuàng)建自定義的Java類。通過@Interceptors注解來(lái)定義相關(guān)的方法簽名
- 我們需要在對(duì)應(yīng)的配置文件中通過plugins來(lái)注冊(cè)自定義的攔截器
我們可以通過攔截器做哪些操作?
- 檢查執(zhí)行的SQL。比如 sql 中有select * . delete from 。。。
- 對(duì)執(zhí)行的SQL的參數(shù)做處理
- 對(duì)查詢的結(jié)果做裝飾處理
- 對(duì)查詢SQL的分表處理
十二、使用MyBatis的mapper接口調(diào)用時(shí)有哪些要求?
MyBatis中的Mapper接口實(shí)現(xiàn)的本質(zhì)是代理模式
- Mapper映射文件的namespace的值必須是Mapper接口對(duì)應(yīng)的全類路徑的名稱
- Mapper接口中的方法名必須在mapper的映射文件中有對(duì)應(yīng)的sql的id
- Mapper接口中的入?yún)㈩愋捅仨毢蚼apper映射文件中的每個(gè)sql 的parameterType類型相同
- Mapper接口中的出參類型必須和mapper映射文件中的么個(gè)sql的resultType類型相同
- 接口名稱和Mapper映射文件同名
十三、如何獲取MyBatis中自增的主鍵
需要獲取自增的主鍵:在同一個(gè)事務(wù)中操作多表。我們需要關(guān)聯(lián)的id信息。
<insert id="xxx" useGeneratedKeys="true" keyProperty="id">
User user = new User();
userMapper.insert(user);
System.out.println("自增的主鍵:id" + user.getId());
十四、不同Mapper中的id是否可以相同?
可以相同:每一個(gè)映射文件的namespace都會(huì)設(shè)置為對(duì)應(yīng)的mapper接口的全類路徑名稱。也就是保證了每一個(gè)Mapper映射文件的namespace是惟一的。那么我們只需要滿足在同一個(gè)映射文件中的id是不同的就可以了
UserMapper.xml: com.boge.mapper.UserMapper #selectList
RoleMapper.xml com.boge.mapper.RoleMapper #selectList
十五、談?wù)勀銓?duì)MyBatis的架構(gòu)設(shè)計(jì)的理解
- 接口層:面向開發(fā)者。提供相關(guān)的API
- 核心層:MyBatis的核心功能的實(shí)現(xiàn):增刪改查操作
- 基礎(chǔ)模塊:由很多相互之間沒用關(guān)聯(lián)的模塊組成。作用是支持核心層來(lái)完成核心的功能
十六、傳統(tǒng)JDBC的不足和MyBatis的解決方案
- 我們需要頻繁的創(chuàng)建和釋放數(shù)據(jù)庫(kù)庫(kù)的連接對(duì)象。會(huì)造成系統(tǒng)資源的浪費(fèi)。從而影響系統(tǒng)的性能,針對(duì)這種情況我們的解決方案是數(shù)據(jù)庫(kù)連接池。然后在MyBatis中的全局配置文件中我們可以設(shè)置相關(guān)的數(shù)據(jù)庫(kù)連接池。當(dāng)然和Spring整合后我們也可以配置相關(guān)的數(shù)據(jù)庫(kù)連接。
- SQL語(yǔ)句我們是直接添加到了代碼中了,造成維護(hù)的成本增加。所以對(duì)應(yīng)SQL的動(dòng)態(tài)性要求比較高。這時(shí)我們可以考慮把SQL和我們的代碼分離,在MyBatis中專門提供了映射文件。我們?cè)谟成湮募型ㄟ^標(biāo)簽來(lái)寫相關(guān)的SQL
- 向SQL中傳遞參數(shù)也很麻煩,因?yàn)镾QL語(yǔ)句的where條件不一定??赡苡泻芏嘀狄部赡芎苌佟U嘉环蛥?shù)需要一一對(duì)應(yīng)。在MyBatis中自動(dòng)完成java對(duì)象和sql中參數(shù)的映射
- 對(duì)于結(jié)果集的映射也很麻煩,主要是SQL本身的變化會(huì)導(dǎo)致解析的難度。我們的解決方案。在MyBatis中通過ResultSetHandler來(lái)自動(dòng)把結(jié)果集映射到對(duì)應(yīng)的Java對(duì)象中。
- 傳統(tǒng)的JDBC操作不支持事務(wù)。緩存。延遲加載等功能。在MyBatis中都提供了相關(guān)的實(shí)現(xiàn)
十七、MyBatis編程步驟是怎么樣的?
- 創(chuàng)建SqlSessionFactory–》SqlSessionFactoryBuilder --》建造成模式 --》Configuration
- 通過創(chuàng)建的SqlSessionFactory對(duì)象來(lái)獲取SqlSession對(duì)象 --》 Executor
- 通過SqlSession對(duì)象執(zhí)行數(shù)據(jù)庫(kù)操作 --》API和Mapper接口代理對(duì)象 --》緩存 --》裝飾者模式
- 調(diào)用SqlSession中的commit方法來(lái)顯示的提交事務(wù) --》 數(shù)據(jù)源和事務(wù)模塊 --》 JDBC和Managed
- 調(diào)式SqlSession中的close方法來(lái)關(guān)閉會(huì)話
十八、當(dāng)實(shí)體中的屬性和表中的字段不一致的情況下怎么辦?
- 我們可以在對(duì)應(yīng)的SQL語(yǔ)句中通過別名的方式來(lái)解決這個(gè)問題
- 我們通過自定義resultMap標(biāo)簽來(lái)設(shè)置屬性和字段的映射關(guān)系
十九、談?wù)勀銓?duì)MyBatis中的Executor的理解
Executor的類型有三類:
- SIMPLE:默認(rèn) SimpleExecutor:每次操作都是一個(gè)新的Statement對(duì)象
- REUSE: ReuseExecutor,會(huì)根據(jù)SQL緩存Statement對(duì)象。實(shí)現(xiàn)Statement對(duì)象的復(fù)用
- BATCH: BatchExecutor 批處理
二十、如何設(shè)置MyBatis的Executor類型
Executor的類型有三類:
- SIMPLE:默認(rèn) SimpleExecutor:每次操作都是一個(gè)新的Statement對(duì)象
- REUSE: ReuseExecutor,會(huì)根據(jù)SQL緩存Statement對(duì)象。實(shí)現(xiàn)Statement對(duì)象的復(fù)用
- BATCH: BatchExecutor 批處理
如何指定我們需要使用的類型呢?
- 可以通過SqlSessionFactory的openSession方法中來(lái)指導(dǎo)對(duì)應(yīng)的處理器類型
- 可以通過全局配置文件中的settings來(lái)配置默認(rèn)的執(zhí)行器
二十一、MyBatis中如何實(shí)現(xiàn)多個(gè)傳參
1.循序傳值
public void selectUser(String name,int deptId);
<select id="selectUser" resultMap="baseResultMap">select * from t_user where user_name = #{0} and dept_id= #{1}
</select>
#{}里面的數(shù)字代表的是入?yún)⒌捻樞?/p>
但是這種方法不建議使用,SQL層次表達(dá)不直觀,而且一旦循序錯(cuò)了很難找到。
2. @Param注解傳值
public void selectUser(@Param("name")String name,@Param("deptId")int deptId);
<select id="selectUser" resultMap="baseResultMap">select * from t_user where user_name = #{name} and dept_id= #{deptId}
</select>
#{}里面的名稱對(duì)應(yīng)的就是@Param注解中修飾的名稱。
這種方案我們是非常推薦使用的。因?yàn)楹苤庇^。
3. 通過Map傳值
public void selectUser(Map<String,Object> map);
<select id="selectUser" parameterType="java.util.Map" resultMap="baseResultMap">select * from t_user where user_name = #{name} and dept_id= #{deptId}
</select>
#{}里面的名稱就是Map中對(duì)應(yīng)的Key
這種方案適合傳遞多個(gè)參數(shù),且參數(shù)靈活應(yīng)變值得推薦
4.通過自定義對(duì)象傳遞
public void selectUser(User user);
<select id="selectUser" parameterType="com.boge.bean.User" resultMap="baseResultMap">select * from t_user where user_name = #{name} and dept_id= #{deptId}
</select>
#{} 中的名稱就是自定義對(duì)象的屬性名稱
這種方案很直觀。但是需要?jiǎng)?chuàng)建一個(gè)實(shí)體類。擴(kuò)展不容易。需要添加屬性。但是代碼的可讀性很高。業(yè)務(wù)邏輯處理也非常方便。值得推薦
二十二、談?wù)勀銓?duì)日志模塊的理解
1。MyBatis中的日志模塊使用了適配器模式
2。如果我們需要適配MyBatis沒有提供的日志框架。那么對(duì)應(yīng)的需要添加相關(guān)的適配類
3。在全局配置文件中設(shè)置日志的實(shí)現(xiàn)
4。在MyBatis的日志框架中提供了一個(gè) jdbc 這個(gè)包。里面實(shí)現(xiàn)了JDBC相關(guān)操作的日志記錄
二十三、談?wù)凪yBatis中能夠記錄SQL執(zhí)行的原理
在MyBatis中對(duì)執(zhí)行JDBC操作的日志記錄的本質(zhì)是創(chuàng)建了相關(guān)核心對(duì)象的代理對(duì)象
- Connection – ConnectionLogger
- PreparedStatement – PreparedStatementLogger
- ResultSet --ResultSetLogger
本質(zhì)就是通過代理對(duì)象來(lái)實(shí)現(xiàn)的。代理對(duì)象中完成相關(guān)的日志操作。然后再調(diào)用對(duì)應(yīng)的目標(biāo)對(duì)象完成相關(guān)的數(shù)據(jù)庫(kù)的操作處理。
二十四、MyBatis中數(shù)據(jù)源模塊的設(shè)計(jì)
在MyBatis中單獨(dú)設(shè)計(jì)了DataSource這個(gè)數(shù)據(jù)源模塊
在使用MyBatis的時(shí)候我們都需要單獨(dú)的設(shè)置DataSource
完成相關(guān)的DataSource節(jié)點(diǎn)的解析
UnpooledDataSource:非數(shù)據(jù)庫(kù)連接池的實(shí)現(xiàn)
PooledDataSource:數(shù)據(jù)庫(kù)連接池的實(shí)現(xiàn)
- 從連接池中獲取連接對(duì)象:如果有空閑連接直接返回?;钴S連接數(shù)是否超過了最大連接數(shù)。是否有連接超時(shí)的連接
- 數(shù)據(jù)庫(kù)連接池關(guān)閉連接。如果空閑連接沒有超過最大連接數(shù)那么就放回空閑隊(duì)列中。否則關(guān)閉真實(shí)的連接
二十五、MyBatis中事務(wù)模塊的設(shè)計(jì)
1。談?wù)勀銓?duì)事務(wù)的理解【ACID】
2。MyBatis中的事務(wù)的管理
事務(wù)接口的定義:定義了事務(wù)的基本行為
3。在MyBatis的事務(wù)管理中有兩個(gè)選擇
- jdbc:在MyBatis中自己處理事務(wù)的管理
- Managed:在MyBatis中沒有處理任何的事務(wù)操作。這種情況下事務(wù)的處理會(huì)交給Spring容器來(lái)管理
4。如何設(shè)置事務(wù)管理的方式
5。在MyBatis中執(zhí)行DML操作事務(wù)的處理邏輯
SqlSession.commit();
二十六、談?wù)勀銓?duì)Mapper接口的設(shè)計(jì)理解
1。談下MyBatis中Mapper接口對(duì)應(yīng)的規(guī)則
2。談下MyBatis中的Mapper接口的設(shè)計(jì)原理–代理模式的使用
3。代理對(duì)象執(zhí)行的邏輯的本質(zhì)還是會(huì)執(zhí)行SqlSession中相關(guān)的DML操作的方法
4。為什么會(huì)多一個(gè)代理對(duì)象的處理
二十七、談?wù)勀銓?duì)Reflector模塊的理解
Reflector是MyBatis中提供的一個(gè)針對(duì)反射封裝簡(jiǎn)化的模塊:簡(jiǎn)化反射的相關(guān)操作。MyBatis是一個(gè)ORM框架。表結(jié)構(gòu)的數(shù)據(jù)和Java對(duì)象中數(shù)據(jù)的映射。那么不可避免的會(huì)存在非常多的反射操作。
Reflector是一個(gè)獨(dú)立的模塊。我們是可以把這個(gè)模塊單獨(dú)抽取出來(lái)直接使用的。
反射模塊的具體的設(shè)計(jì)
二十八、談?wù)勀銓?duì)MyBatis中的類型轉(zhuǎn)換模塊的理解
MyBatis中是如何解決Java中的類型和數(shù)據(jù)庫(kù)中字段類型的映射。
類型轉(zhuǎn)換處理器的設(shè)計(jì)
TypeHandler --》 BaseTypeHandler—》具體的TypeHandler
預(yù)處理占位符賦值
二十九、談?wù)凪yBatis和Spring的整合的理解
1?;卮鸬谋容^簡(jiǎn)單些。梳理下MyBatis和Spring整合的步驟
- 單純的Spring和MyBatis的整合
- 在SpringBoot項(xiàng)目中的整合
2。重點(diǎn)分析下整合的jar包的原理
MybatisSqlSessionFactoryBean–》 這個(gè)就是我們需要關(guān)注的重點(diǎn)了。
三十、談?wù)勀銓?duì)MyBatis的理解
MyBatis是一個(gè)非常主流的半自動(dòng)的ORM框架。非常簡(jiǎn)便的幫助我們完成相關(guān)的數(shù)據(jù)庫(kù)操作。
提供動(dòng)態(tài)SQL,緩存和延遲加載等高級(jí)功能。
然后整體的架構(gòu)非常簡(jiǎn)單
- 外層接口
- 核心處理層
- 基礎(chǔ)模塊