您好,登錄后才能下訂單哦!
這篇文章主要講解了“MyBatis3源碼解析之怎么獲取數據源”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“MyBatis3源碼解析之怎么獲取數據源”吧!
再貼一個JDBC運行的測試方法,流程為:
加載JDBC驅動;
獲取數據庫連接;
創建JDBC Statements對象;
設置SQL語句的傳入參數;
執行SQL語句并獲得查詢結果;
對查詢結果進行轉換處理并將處理結果返回;
釋放相關資源(關閉Connection,關閉Statement,關閉ResultSet);
@Test public void jdbcTest(){ String driver = "com.mysql.cj.jdbc.Driver"; String url = "jdbc:mysql://localhost:3306/news?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true"; String user = "root"; String pwd = "root123456"; Connection connection=null; ResultSet rs=null; PreparedStatement stmt=null; try { Class.forName(driver); //獲取數據庫連接 connection = DriverManager.getConnection(url,user,pwd); String sql = "select * from t_level where name=?"; //創建Statement對象(每一個Statement為一次數據庫執行請求) stmt=connection.prepareStatement(sql); //設置傳入參數 stmt.setString(1,"zhangsan"); //執行SQL語句 rs = stmt.executeQuery(sql); ResultSetMetaData metaData =rs.getMetaData(); //處理查詢結果-----此處未做操作 int columnCount= metaData.getColumnCount(); System.out.println(columnCount); } 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(); } } }
JDBC 底層沒有用連接池,操作數據庫需要頻繁的創建和關閉連接,消耗很大的資源;
原生的 JDBC 代碼在 Java 中,一旦需要修改 SQL,Java 需要整體編譯,不利于系統維護;
使用 PreparedStatement 預編譯的話,對變量進行設置 1、2、3 等數字,這樣的序號不利于維護;
返回 result 結果集也需要硬編碼。
拿JDBC測試用例和上文mybatis的測試用例對比,可以發現哪些些共同點?
@Test public void test() throws IOException { InputStream input = Resources.getResourceAsStream("SqlSessionConfig.xml"); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(input); SqlSession sqlSession = sessionFactory.openSession(); LevelDao dao = sqlSession.getMapper(LevelDao.class); List<Level> all = dao.findAll(); }
首先他們都要有數據源,這是毋庸置疑的。其次還要有執行sql語句,再有就是執行操作。
接下來進入到源碼分析階段。
由于我們是根據官網 Building SqlSessionFactory from XML的方式來測試demo的,接下來我們的解析就按照XML文件配置形式來講解。
數據源4大元素包括:驅動、 url、 用戶名、 密碼。
在看代碼之前,先看一下我們的配置文件結構。
mybatis是什么時候獲取到數據源的呢?要從測試方法生成SqlSessionFactory說起。
通過斷點進入到SqlSessionFactoryBuilder
的build
方法中,方法體就兩行關鍵代碼,首先new了一個XML 配置生成器
,接著調用了其parse()生成一個Configuration
對象。
public SqlSessionFactory build(Reader reader, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { } } } public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); }
parse方法執行了下面這條語句:
parseConfiguration(parser.evalNode("/configuration"));
parser.evalNode
會生成一個mybatis封裝的XNode
對象,copy后發現就是我們配置文件中<configuration>
標簽中的內容。
進入到parseConfiguration
方法中,可以看出好多方法的字符串參數都和我們<configuration>
標簽中的一些標簽名稱相同。沒錯,每一步都是去掃描到對應參數的標簽內容從而進行一些配置處理。
private void parseConfiguration(XNode root) { try { //issue #117 read properties first propertiesElement(root.evalNode("properties")); Properties settings = settingsAsProperties(root.evalNode("settings")); loadCustomVfs(settings); loadCustomLogImpl(settings); typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); reflectorFactoryElement(root.evalNode("reflectorFactory")); settingsElement(settings); // read it after objectFactory and objectWrapperFactory issue #631 environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }
我們此處不研究其他處內容,直接看environmentsElement
方法的內容。root.evalNode("environments")
返回的XNode對象的value就是我們的environments
標簽內容。
進入到environmentsElement
方法中,會循環遍歷下一級的environment
,此處便是解析xml配置多數據源的地方。
private void environmentsElement(XNode context) throws Exception { if (context != null) { if (environment == null) { environment = context.getStringAttribute("default"); } //xml配置多數據源 for (XNode child : context.getChildren()) { String id = child.getStringAttribute("id"); if (isSpecifiedEnvironment(id)) { TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager")); //<dataSource></dataSource> DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource")); //獲得到數據庫源 DataSource dataSource = dsFactory.getDataSource(); Environment.Builder environmentBuilder = new Environment.Builder(id) .transactionFactory(txFactory) .dataSource(dataSource); configuration.setEnvironment(environmentBuilder.build()); } } } }
dataSourceElement
方法會拿到dataSource
標簽的內容生成一個DataSourceFactory
,并根據我們的配置給其屬性賦值。
通過getDataSource()
方法便可以拿到我們的數據源。
最后調用configuration.setEnvironment
給到全局配置中的。
執行流程圖如下:
感謝各位的閱讀,以上就是“MyBatis3源碼解析之怎么獲取數據源”的內容了,經過本文的學習后,相信大家對MyBatis3源碼解析之怎么獲取數據源這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。