模仿與學習MyBatis - 1.2 DataSource與Session

本文收錄於模仿與學習MyBatis系列


綜述

本篇將實現1.1章中提到的兩個類:

  • DataSource:實現標準的javax.sql.DataSource接口, 用於獲取數據庫連接。
  • Session:可以直接調用exec(sql)來執行sql語句(在DataSource指定的數據庫中操作)

最終產生的是一個Java Maven項目,代碼存在github


DataSource

public class VDataSource implements DataSource {

    private String url;
    private String user;
    private String password;

    // 構架函數,創建時嘗試加載數據庫驅動類
    public VDataSource(String driverClassName, String url, String user, String password) throws ClassNotFoundException {
        Class.forName(driverClassName); 
        this.url = url;
        this.user = user;
        this.password = password;
    }

    // 使用自帶的java.sql.DriverManager,代入數據庫信息取出一個連接
    @Override
    public Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }
}

DataSource其實並不是非常重要的東西,通常使用的是現成的,而非自己去寫,此處只是稍微提一提。先看Class.forName(driverClassName),這句話的功能是加載驅動類。(每種數據庫都一個與java對接的類。
例如,使mysql就要代入com.mysql.jdbc.Driver)那麼,從哪裏獲取這個類呢?可以選擇上網下載jar包導入,我的做法是在pom.xml配置文件中引入mysql在java上的包:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.29</version>
</dependency>

加載後,由於連接信息已記錄在VDataSource中了,獲取連接只需要使用自帶的DriverManager.getConnection即可。還有更高級的寫法,比如線程唯一的連接,連接的回收等等,但通常使用MyBatis時不會使用它自帶的,都是用tomcat\spring\c3p0等提供的DataSource。
所以此處略去不談。


Session

模仿MyBatis框架,示意性的寫一個接口

public interface Session {
    void exec(String sql) throws SQLException;
}

然後新建一個VSession類實現這個接口

public class VSession implements Session {

    private DataSource dataSource;
    private Connection conn;

    public VSession(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    // 若還Session新建後未連接過,從dataSource中獲取一個
    public Connection getConnection() throws SQLException {
        if (conn == null) {
            conn = dataSource.getConnection();
        }
        return conn;
    }

    @Override
    public void exec(String sql) throws SQLException {
        Statement stmt = null;
        ResultSet rs = null;
        try {
            // 從連接中創建一個statement
            stmt = getConnection().createStatement();
            // statement執行一句sql查詢
            rs = stmt.executeQuery(sql);
            // 結果的元數據,包括別名、列名、類型等
            ResultSetMetaData rsmd = rs.getMetaData();
            // 將所有結果輸出
            if (rs.next()) {
                for (int i=1; i<=rsmd.getColumnCount(); i++) {
                    System.out.println(rsmd.getColumnLabel(i)+"="+rs.getObject(i));
                }
                System.out.println();
            }
        } finally {
            if (rs != null) rs.close();
            if (stmt != null) stmt.close();
        }
    }

}

在這段代碼中,可以看到清晰的操作流程。

  • 每一次執行exec(sql),通過getConnection()獲取conn。
  • 在第一次執行getConnection()時,conn還爲空,這時候執行conn = dataSource.getConnection()的初始化,從前面實現的VDataSource類中獲取到數據庫連接。
  • 通過conn.createStatement()創建出一個Statement stmt,類似於一個sql容器類,並通過stmt.executeQuery(sql)執行查詢的sql語句。
  • 取出元數據,將詳細結果輸出

通過以上,已經完完整整的實現了一個基礎的Session,可以exec(sql)來進行數據庫查詢操作了。


測試

最後附上一段測試代碼:

public class MyTest {
    private static String driverClassName = "com.mysql.jdbc.Driver";
    // 數據庫可改爲自己需要的地址
    private static String url = "jdbc:mysql://localhost:3306/webserver?useUnicode=true&characterEncoding=utf8";

    public static void main(String args[]) throws Exception {
        // 創建VDataSource
        DataSource data = new VDataSource(driverClassName, url, "root", "123456");
        // 創建Session
        Session session = new VSession(data);
        // 執行查詢sql
        session.exec("select * from article where id=1");
    }
}

結果如下圖,和預期一致,此篇目的達成。

id=1
title=歡迎來到自由茶社
brief=這裏是大門的入口
content=這裏是大門的入口
father_id=0
author_name=me
create_time=2016-11-16 23:44:36.0
modify_time=2016-12-05 15:29:47.0

以上

下一篇:模仿與學習MyBatis - 1.3 xml配置的解析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章