衆所周知數據庫鏈接的過程,可是最近面試的人(菜面菜),都說用的SSM框架,可是我問了一下,mybatis是怎麼鏈接上mysql的,基本上都會說:配置好的,直接用了,今天我來拋磚引玉一下,歡迎拍磚!java
什麼是JDBC?mysql
Java語言訪問數據庫的一種規範,是一套API。JDBC (Java Database Connectivity) API,即Java數據庫編程接口,是一組標準的Java語言中的接口和類,使用這些接口和類,Java客戶端程序能夠訪問各類不一樣類型的數據庫。JDBC規範採用接口和實現分離的思想設計了Java數據庫編程的框架。接口包含在java.sql及javax.sql包中,其中java.sql屬於JavaSE,javax.sql屬於JavaEE。爲了使客戶端程序獨立於特定的數據庫驅動程序,JDBC規範建議開發者使用基於接口的編程方式,即儘可能使應用僅依賴java.sql及javax.sql中的接口和類。面試
JAVA使用JDBC訪問數據庫的步驟:spring
1.獲得數據庫驅動程序sql
2.建立數據庫鏈接數據庫
3.執行SQL語句編程
4.獲得結果集設計模式
5.對結果集作相應的處理(增,刪,改,查)api
6.關閉資源:這裏釋放的是DB中的資源session
mysql的驅動包提供了java.sql.Driver這個SPI的實現,實現類是com.mysql.jdbc.Driver,在mysql-connector-java-5.1.6.jar中,咱們能夠看到有一個META-INF/services目錄,目錄下有一個文件名爲java.sql.Driver的文件,其中的內容是com.mysql.jdbc.Driver。
在運行DriverManager.getDriver並傳入參數「com.mysql.jdbc.Driver」時,DriverManager會從mysql-connector-java-5.1.6.jar中找到com.mysql.jdbc.Driver並實例化返回一個com.mysql.jdbc.Driver的實例。而SPI(Service Provider Interface)是指一些提供給你繼承、擴展,完成自定義功能的類、接口或者方法。
private class SqlSessionInterceptor implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { SqlSession sqlSession = getSqlSession( SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator); try { Object result = method.invoke(sqlSession, args); if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { // force commit even on non-dirty sessions because some databases require // a commit/rollback before calling close() sqlSession.commit(true); } return result; } catch (Throwable t) { Throwable unwrapped = unwrapThrowable(t); if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) { // release the connection to avoid a deadlock if the translator is no loaded. See issue #22 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); sqlSession = null; Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped); if (translated != null) { unwrapped = translated; } } throw unwrapped; } finally { if (sqlSession != null) { closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); } } } }
sqlSessionTemplate.SqlSessionInterceptor源碼,有沒有一種很熟悉的感受?至於getConnection本身去看;用過ElasticSearch和Redis的童鞋,細心的童鞋會發現鏈接字符串都大同小異,鏈接都是相似的,標準的鏈接方式,提升效率,有效控制鏈接;
ElasticSearch的鏈接字符串:
protected SearchResponse getSearchResponse(String fieldName, String indexName) { client = null; SearchResponse response = null; try { getClient(); MaxAggregationBuilder aggregation = AggregationBuilders .max("agg") .field(fieldName); SearchRequestBuilder request = client.prepareSearch(indexName).addAggregation(aggregation); response = request.execute().actionGet(); } catch (Exception ex) { logger.error("getSearchResponse", ex); } finally { if (client != null) { client.close(); } return response; } }
Jedis鏈接字符串:
執行命令以下: Jedis jedis = null; try { jedis = jedisPool.getResource(); //具體的命令 jedis.executeCommand() } catch (Exception e) { logger.error("op key {} error: " + e.getMessage(), key, e); } finally { //注意這裏不是關閉鏈接,在JedisPool模式下,Jedis會被歸還給資源池。 if (jedis != null) jedis.close(); }
攔截器的實現都是基於代理的設計模式實現的,簡單的說就是要創造一個目標類的代理類,在代理類中執行目標類的方法並在方法以前執行攔截器代碼,攔截器通常有登錄攔截器——驗證會話信息,權限攔截器——驗證權限信息,那麼SqlSessionInterceptor是幹什麼的?
Mybatis攔截器設計的一個初衷就是爲了供用戶在某些時候能夠實現本身的邏輯而沒必要去動Mybatis固有的邏輯。打個比方,對於Executor,Mybatis中有幾種實現:BatchExecutor、ReuseExecutor、SimpleExecutor和CachingExecutor。
這個時候若是你以爲這幾種實現對於Executor接口的query方法都不能知足你的要求,那怎麼辦呢?是要去改源碼嗎?固然不。咱們能夠創建一個Mybatis攔截器用於攔截Executor接口的query方法,在攔截以後實現本身的query方法邏輯,以後能夠選擇是否繼續執行原來的query方法。容許你在已映射語句執行過程當中的某一點進行攔截調用。有的用Mybatis攔截器統封裝分頁,有的用它實現讀寫分離等,若是讀寫分離仍是建議配置多數據源;
spring整合mybatis以後,經過動態代理的方式,使用SqlSessionTemplate持有的sqlSessionProxy屬性來代理執行sql操做,由spring管理的sqlSeesion在sql方法(增刪改查等操做)執行完畢後就自行關閉了sqlSession,不須要咱們對其進行手動關閉。
願你有情人終成眷屬,願你有個有趣的靈魂,願你拍我一磚!