本文收錄於模仿與學習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
以上