模仿与学习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配置的解析

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