歡迎關注文章系列,一塊兒學習 《提高能力,漲薪可待篇》
《面試知識,工做可待篇》
《實戰演練,拒絕996篇》
也歡迎關注微信公衆號【Ccww筆記】,原創技術文章第一時間推出
若是此文對你有幫助、喜歡的話,那就點個讚唄,點個關注唄!html
往期文章系列:java
mybatis在處理#{}時,會將sql中的#{}替換爲?號,調用PreparedStatement的set方法來賦值。git
mybatis在處理${}時,就是把${}替換成變量的值。程序員
使用#{}能夠有效的防止SQL注入,提升系統安全性。緣由在於:預編譯機制。預編譯完成以後,SQL的結構已經固定,即使用戶輸入非法參數,也不會對SQL的結構產生影響,從而避免了潛在的安全風險。github
預編譯是提早對SQL語句進行預編譯,而其後注入的參數將不會再進行SQL編譯。咱們知道,SQL注入是發生在編譯的過程當中,由於惡意注入了某些特殊字符,最後被編譯成了惡意的執行操做。而預編譯機制則能夠很好的防止SQL注入。面試
既然${}會引發sql注入,爲何有了#{}還須要有${}呢?那其存在的意義是什麼?redis
#{}主要用於預編譯,而預編譯的場景其實很是受限,而${}用於替換,不少場景會出現替換,而這種場景可不是預編譯sql
數據庫的訪問底層是經過tcp實現的,當連接中斷是程序是沒法得知,致使程序一直會停頓一段時間在這,最終會致使用戶體驗很差,所以面對數據庫鏈接中斷的異常,該怎麼設置mybatis呢?數據庫
connection操做底層是一個循環處理操做,所以能夠進行時間有關的參數:緩存
數據庫服務器活的槓槓的,可是由於網絡用塞,客戶端仍然連不上服務器端,這個時候就要設置timeout,別一直傻等着
插入的過程通常都是分兩步的:先判斷是否存在記錄,沒有存在則插入不然不插入。若是存在併發操做,那麼同時進行了第一步,而後你們都發現沒有記錄,而後都插入了數據從而形成數據的重複
解決插入重複的思路 :
總結:多線程同時插入數據,誰獲取鎖並插入數據成功了其餘線程不作任何操做。當插入數據失敗後,其餘線程搶鎖進行插入數據。
數據庫插入百萬級數據的時候,還沒操做完,可是把服務器重啓了,數據庫會繼續執行嗎? 仍是直接回滾了?
不會自動繼續執行,不會自動直接回滾 ,但能夠依據事務日誌進行回滾或者進行執行。
事務開啓時,事務中的操做,都會先寫入存儲引擎的日誌緩衝中,在事務提交以前,這些緩衝的日誌都須要提早刷新到磁盤上持久化 ,兩種類型:
在事務執行的過程當中,除了記錄redo log,還會記錄必定量的undo log。
Java客戶端中的一個Connection不是在MySQL中就對應一個線程來處理這個連接,而是:
監聽socket的主線程+線程池裏面固定數目的工做線程來處理的
高性能服務器端端開發底層主要靠I/O複用來處理,這種模式:
單線程+事件處理機制
在MySQL有一個主線程,這是單線程(與Java中到處強調多線程的思想有點不一樣哦),它不斷的循環查看是否有socket是否有讀寫事件,若是有讀寫事件,再從線程池裏面找個工做線程處理這個socket的讀寫事件,完事以後工做線程會回到線程池。
string name = "%Ccww%";
list<name> names = mapper.selectName(name);
複製代碼
<select id="selectName">
select * from users where name like #{value}
</select>
複製代碼
<select id="selectName">
select * from users where name like "%"#{value}"%"
</select>
複製代碼
接口綁定 : 在MyBatis中任意定義接口,而後把接口裏邊的方法和SQL語句綁定,咱們能夠直接調用接口方法,比起SqlSession提供的方法咱們能夠有更加靈活的選擇和設置
接口綁定有兩種實現方式 :
Dao接口爲Mapper接口。
接口的全限名爲映射文件中的namespace的值;
接口的方法名爲映射文件中Mapper的Statement的id值;
接口方法內的參數爲傳遞給sql的參數。
Mapper接口是沒有實現類的,當調用接口方法時,接口全限名+方法名拼接字符串做爲key值,可惟必定位一個MapperStatement。在Mybatis中,每個 <select>、<insert>、<update>、<delete>標籤,都會被解析爲一個MapperStatement對象
Mapper接口裏的方法,是不能重載的,由於是使用 全限名+方法名 的保存和尋找策略。Mapper 接口的工做原理是JDK動態代理,Mybatis運行時會使用JDK動態代理爲Mapper接口生成代理對象proxy,代理對象會攔截接口方法,轉而執行MapperStatement所表明的sql,而後將sql執行結果返回。
基於上面,能夠得知
Statement=namespace+id
若是配置了namespace能夠重複的 ,但若是沒有配置namespace的話,那麼相同的id就會致使覆蓋了。
(1)一級緩存: 基於 PerpetualCache 的 HashMap 本地緩存,其存儲做用域爲 Session,當 Session flush 或 close 以後,該 Session 中的全部 Cache 就將清空,默認打開一級緩存。
(2)二級緩存與一級緩存其機制相同,默認也是採用 PerpetualCache,HashMap 存儲,不一樣在於其存儲做用域爲 Mapper(Namespace),而且可自定義存儲源,如 Ehcache。默認不打開二級緩存,要開啓二級緩存,使用二級緩存屬性類須要實現Serializable序列化接口(可用來保存對象的狀態),可在它的映射文件中配置 ;
(3)對於緩存數據更新機制,當某一個做用域(一級緩存 Session/二級緩存Namespaces)的進行了C/U/D 操做後,默認該做用域下全部 select 中的緩存將被 clear。
Mybatis 使用 RowBounds 對象進行分頁,它是針對 ResultSet 結果集執行的內存分頁,而非數據庫分頁。
在實際場景下,使用以下兩種方案:
這二者都是基於數據庫分頁,差異在於前者是工程師手動編寫分頁條件,後者是插件自動添加分頁條件。
分頁插件的基本原理是使用 Mybatis 提供的插件接口,實現自定義分頁插件。在插件的攔截方法內,攔截待執行的 SQL ,而後重寫 SQL ,根據dialect 方言,添加對應的物理分頁語句和物理分頁參數。
舉例:SELECT * FROM student
,攔截 SQL 後重寫爲:select * FROM student LIMI 0,10
。
目前市面上目前使用比較普遍的 MyBatis 分頁插件有:
Mybatis僅支持association關聯對象和collection關聯集合對象的延遲加載,association指的就是一對一,collection指的就是一對多查詢。
在Mybatis配置文件中,能夠配置是否啓用延遲加載:
lazyLoadingEnabled=true|false。
原理是,使用CGLIB建立目標對象的代理對象,當調用目標方法時,進入攔截器方法.
好比調用a.getB().getName(),攔截器invoke()方法發現a.getB()是null值,那麼就會單獨發送事先保存好的查詢關聯B對象的sql,把B查詢上來,而後調用a.setB(b),因而a的對象b屬性就有值了,接着完成a.getB().getName()方法的調用。這就是延遲加載的基本原理。
固然了,不光是Mybatis,幾乎全部的包括Hibernate,支持延遲加載的原理都是同樣的。
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生命週期範圍內
在Mybatis配置文件中,能夠指定默認的ExecutorType執行器類型,也能夠手動給DefaultSqlSessionFactory的建立SqlSession的方法傳遞ExecutorType類型參數。
總結:
參考文章:
也歡迎關注微信公衆號【Ccww筆記】,原創技術文章第一時間推出
若是此文對你有幫助、喜歡的話,那就點個讚唄,點個關注唄!![]()