在mybatis的基礎知識中咱們已經能夠對mybatis的工做方式窺斑見豹。可是,爲何還要要學習mybatis的工做原理?由於,隨着mybatis框架的不斷髮展,現在已經愈來愈趨於自動化,從代碼生成,到基本使用,咱們甚至不須要動手寫一句SQL就能夠完成一個簡單應用的所有CRUD操做。從原生mybatis到mybatis-spring,到mybatis-plus再到mybatis-plus-spring-boot-starter。spring在發展,mybatis一樣在隨之發展。html
Mybatis本是apache的一個開源項目iBatis,2010年這個項目由apache software foundation遷移到了google code,而且更名爲MyBatis。java
iBatis一詞來源於"internet"和"abatis"的組合,是一個基於java的持久層框架。iBatis提供的持久層框架包括SQLMaps和Data Access Objects(DAO)spring
Mybatis是支持普通SQL查詢,存儲過程和高級映射的優秀持久層框架。MyBatis消除了幾乎全部的JDBC代碼和參數的手工設置以及結果集的檢索。Mybatis使用簡單的XML或註解用於配置和原始映射,將接口和java的POJOs映射成數據庫中的記錄。sql
每一個MyBatis應用程序主要都是使用SqlSessionFactory實例的,一個SqlSessionFactory實例能夠經過SqlSessionFactoryBuilder得到。SqlSessionFactoryBuilder能夠從一個xml配置文件或者一個預約義的配置類的實例得到。數據庫
用xml文件構建sqlsessionfactory實例是很是簡單的事情。推薦在這個配置中使用相似路徑資源,但你可使用任何Reader實例,包括用文件路徑或file://開頭的url建立實例。MyBatis有一個實用類——resources,它有不少方法,能夠方便地從類路徑及其餘位置加載資源。apache
mybatis應用程序經過SqlSessionFactoryBuilder從mybatis-config.xml配置文件(也能夠用Java文件配置的方式,須要添加@Configuration)中構建出SqlSessionFactory(SqlSessionFactory是線程安全的);api
而後,SqlSessionFactory的實例直接開啓一個SqlSession,再經過SqlSession實例得到Mapper對象並運行Mapper映射的SQL語句,完成對數據庫的CRUD和事務提交,以後關閉SqlSession。緩存
說明:SqlSession是單線程對象,由於它是非線程安全的,是持久化操做的獨享對象,相似jdbc中的Connection,底層就封裝了jdbc鏈接。安全
一、加載mybatis全局配置文件(數據源、mapper映射文件等),解析配置文件,MyBatis基於XML配置文件生成Configuration,和一個個MappedStatement(包括了參數映射配置、動態SQL語句、結果映射配置),其對應着<select | update | delete | insert>標籤項。session
二、SqlSessionFactoryBuilder經過Configuration對象生成SqlSessionFactory,用來開啓SqlSession。
三、SqlSession對象完成和數據庫的交互:
a、用戶程序調用mybatis接口層api(即Mapper接口中的方法)
b、SqlSession經過調用api的Statement ID找到對應的MappedStatement對象
c、經過Executor(負責動態SQL的生成和查詢緩存的維護)將MappedStatement對象進行解析,sql參數轉化、動態sql拼接,生成jdbc Statement對象
d、JDBC執行sql。
e、藉助MappedStatement中的結果映射關係,將返回結果轉化成HashMap、JavaBean等存儲結構並返回。
MyBatis優勢
一、半自動化的ORM實現(實體類和SQL語句之間創建映射關係)
二、SQL代碼從程序代碼中完全分離,可重用
三、與JDBC相比,減小了50%以上的代碼量
四、小巧靈活、簡單易學,是最簡單的持久化框架
五、提供XML標籤,支持編寫動態SQL
六、提供映射標籤,支持對象與數據庫的ORM字段映射
MyBatis缺點
一、SQL語句編寫工做量大,對開發人員有必定sql技術要求
二、數據庫移植性差(不一樣數據庫,sql語句語法有所不一樣)
一、經過Reader對象讀取Mybatis映射文件
二、經過SqlSessionFactoryBuilder對象建立SqlSessionFactory對象
三、獲取當前線程的SQLSession
四、事務默認開啓
五、經過SQLSession讀取映射文件中的操做編號,從而讀取SQL語句
六、提交事務
七、關閉資源
JDBC是Java提供的一個操做數據庫的API; MyBatis是一個持久層ORM框架,底層是對JDBC的封裝。
MyBatis對JDBC操做數據庫作了一系列的優化:
(1) mybatis使用已有的鏈接池管理,避免浪費資源,提升程序可靠性。
(2) mybatis提供插件自動生成DAO層代碼,提升編碼效率和準確性。
(3) mybatis 提供了一級和二級緩存,提升了程序性能。
(4) mybatis使用動態SQL語句,提升了SQL維護。(此優點是基於XML配置)
(5) mybatis對數據庫操做結果進行自動映射
jdbc操做步驟總結以下:
一、 加載數據庫驅動
二、 建立並獲取數據庫連接
三、 建立jdbc statement對象
四、 設置sql語句
五、 設置sql語句中的參數(使用preparedStatement)
六、 經過statement執行sql並獲取結果
七、 對sql執行結果進行解析處理(對查詢結果進行轉換處理並將處理結果返回)
八、 釋放資源(resultSet、preparedstatement、connection)
jdbc問題總結以下:
一、 數據庫連接建立、釋放頻繁形成系統資源浪費從而影響系統性能,若是使用數據庫連接池可解決此問題。
二、 Sql語句寫在代碼中形成代碼不易維護,實際應用sql變化的可能較大,sql變更須要改變java代碼。
三、 向sql語句傳參數麻煩,由於sql語句的where條件不必定,可能多也可能少,佔位符須要和參數一一對應。
四、 對結果集解析麻煩,sql變化致使解析代碼變化,且解析前須要遍歷,若是能將數據庫記錄封裝成pojo對象解析比較方便。
(由此引申到了Mybatis框架)
代碼示例:
public static List<Map<String,Object>> queryForList(){ Connection connection = null; ResultSet rs = null; PreparedStatement stmt = null; List<Map<String,Object>> resultList = new ArrayList<Map<String,Object>>(); try { //加載JDBC驅動 Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); String url = "jdbc:oracle:thin:@localhost:1521:ORACLEDB"; String user = "trainer"; String password = "trainer"; //獲取數據庫鏈接 connection = DriverManager.getConnection(url,user,password); String sql = "select * from userinfo where user_id = ? "; //建立Statement對象(每個Statement爲一次數據庫執行請求) stmt = connection.prepareStatement(sql); //設置傳入參數 stmt.setString(1, "zhangsan"); //執行SQL語句 rs = stmt.executeQuery(); //處理查詢結果(將查詢結果轉換成List<Map>格式) ResultSetMetaData rsmd = rs.getMetaData(); int num = rsmd.getColumnCount(); while(rs.next()){ Map map = new HashMap(); for(int i = 0;i < num;i++){ String columnName = rsmd.getColumnName(i+1); map.put(columnName,rs.getString(columnName)); } resultList.add(map); } } catch (Exception e) { e.printStackTrace(); } finally { try { //關閉結果集 if (rs != null) { rs.close(); rs = null; } //關閉執行 if (stmt != null) { stmt.close(); stmt = null; } if (connection != null) { connection.close(); connection = null; } } catch (SQLException e) { e.printStackTrace(); } } return resultList; }
參考:
一、https://blog.csdn.net/xudan1010/article/details/53435018(推薦,來龍去脈總結得很明確)
二、http://www.javashuo.com/article/p-dubabhrv-dw.html
三、http://www.javashuo.com/article/p-eawdggfh-bg.html
四、http://www.javashuo.com/article/p-nqvtutzj-hq.html
五、MyBatis API文檔:http://www.mybatis.org/mybatis-3/zh/getting-started.html