標籤:spring 源碼 framework 架構 jdbc
在百度百科上找了一段定義ORM的話:對象關係映射(英語:Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程式技術,用於實現物件導向程式設計語言裡不同類型系統的資料之間的轉換。從效果上說,它其實是建立了一個可在程式設計語言裡使用的“虛擬對象資料庫”。那麼ORM Framework就是提供對象到資料庫關係映射的一套編程模型。現在流行的MyBaits、Hibernate都是這種架構。本章開始我們就來分析下這兩種架構源碼的分析,從而更深入的理解什麼事ORM。
在開始分析MyBaits3,Hibernate4這些當前比較流行的ORM架構的源碼之前我們先來看看JDBC,它是所有這些架構的基礎。說到JDBC,我們首先來看看java.sql包下有哪些類。
我們再來看一下一次jdbc訪問資料的完整過程。
Connection con = null; Statement stmt = null; ResultSet rs = null; try{ Class.forName("com.mysql.jdbc.Driver"); con = DriverManager.getConnection("jdbc:mysql://localhost:3306/database", "root", "123456"); stmt = con.createStatement(); String sql = "select * from `table`"; rs = stmt.executeQuery(sql); ResultSetMetaData rsmd = rs.getMetaData(); int j = 0; j = rsmd.getColumnCount(); for(int k = 0; k<j; k++){ System.out.print(rsmd.getCatalogName(k+1)); System.out.print("\t"); } while(rs.next()) { for(int i=0;i<j;i++) { System.out.print(rs.getString(i+1)); System.out.print("\t"); } } } catch(Exception e1) { System.out.println(e1.toString()); } finally{ try { if(rs != null) rs.close(); if(stmt != null) stmt.close(); if(con != null) con.close(); } catch(SQLException e) { System.out.println(e.toString()); } }
Class.forName(String)是java reflection中用來載入類的,這裡載入了一個驅動,然後DriverManager.getConnection()擷取資料庫連接,我們來看看DriverManager類。
DriverManager做為驅動管理器,有個內部類DriverInfo用於存取驅動程式的資訊,維護著一個Driver對象。在載入了驅動程式後就需要從DriverManager中擷取資料庫連接。
public static Connection getConnection(String url, String user, String password) throws SQLException { java.util.Properties info = new java.util.Properties(); if (user != null) { info.put("user", user); } if (password != null) { info.put("password", password); } return (getConnection(url, info, Reflection.getCallerClass())); }
private static Connection getConnection( String url, java.util.Properties info, Class<?> caller) throws SQLException { /* * 如果callerCl是空,我們就得檢查應用的類載入器,這樣就能載入rt.jar以外的JDBC驅動 */ ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; synchronized (DriverManager.class) { // synchronize loading of the correct classloader. if (callerCL == null) { callerCL = Thread.currentThread().getContextClassLoader(); } } if(url == null) { throw new SQLException("The url cannot be null", "08001"); } println("DriverManager.getConnection(\"" + url + "\")"); SQLException reason = null; for(DriverInfo aDriver : registeredDrivers) { //如果該類載入器無載入該驅動的許可權則跳過 if(isDriverAllowed(aDriver.driver, callerCL)) { try { println(" trying " + aDriver.driver.getClass().getName()); //利用驅動嘗試串連資料庫 Connection con = aDriver.driver.connect(url, info); if (con != null) { println("getConnection returning " + aDriver.driver.getClass().getName()); return (con); } } catch (SQLException ex) { if (reason == null) { reason = ex; } } } else { println(" skipping: " + aDriver.getClass().getName()); } } //省略部分代碼... }
DriverManager會在類載入時調用靜態代碼塊初始化載入資料庫驅動,當使用者用getConnection時Driver會嘗試去串連資料庫,一旦有一種Driver能串連當前資料庫就返回這個串連。以Mysql的mysql-connector-java為例如果希望自己的資料庫能被JDBC資料庫連接必須實現Connection介面。Connection不僅能提供事務操作還有個抽象方法createStatement能建立一個sql聲明,這裡就講到了JDBC的第二個比較重要的類Statement。同樣這個也是一個介面,需要不同資料庫的開發商自己提供實現,這個對象主要的作用就是執行sql返回ResultSet,同樣這個ResultSet也是一個介面需要提供第三方實現,它類似一個Table資料結構,每次調用next()它就指向下一條資料庫記錄,針對不同類型欄位調用不同的getXXX(String columnName)就能擷取該條記錄對應欄位的值。除了以上的這些主要介面,JDBC還提供了描述資料庫屬性的DatabaseMetaData介面和一些Date之類類型類和異常類。
從以上這些分析我們就可以看出,實際上JDBC API很簡單,它只是一個java到資料庫的橋樑,只提供了一個大致規範,所有對特定資料庫的操作都需要第三方來提供實現。
ORM framework源碼分析:引言之Java JDBC