一觉醒来,受到梦的启发,自研了一套K/V数据库系统,因为"客户"一直催促我提供数据库的JDBC驱动,无奈之下,只好花费一个上午的时间为用户编写一个。
我们知道,JDBC只定义一系列的接口, 具体的实现需要由不同厂商提供的,我们首先需要实现java.sql.Driver这个接口:
package org.littlestar.propsjdbc;
//import ...
public class Driver implements java.sql.Driver {
// 当class loader加载本类时,向DriverManager注册该驱动
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException e) {
throw new RuntimeException("Can't register driver!");
}
}
@Override
public Connection connect(String url, Properties info) throws SQLException {
return new ConnectionImpl(url);
}
@Override
public boolean acceptsURL(String url) throws SQLException {
if (url == null) {
throw new SQLException("url is null.");
}
// 接受'jdbc:props:'类型的URL
return url.trim().startsWith("jdbc:props:");
}
// ... 其它接口实现省略
}
DriverManager是通过JDK内置的SPI(Service Provider Interface)机制来发现我编写的’org.littlestar.propsjdbc.Driver’实现。所以我们需要在META-INF/services/目录里创建一个以服务接口命名的文件, 文件名为"java.sql.Driver"的文件, 该文件内容为接口实现类: ‘org.littlestar.propsjdbc.Driver’。当DriverManager在调ensureDriversInitialized()方法的时候,ServiceLoader会查找类路径下的META-INF/services/java.sql.Driver文件,并加载其定义的接口实现类。
private static void ensureDriversInitialized() {
//...
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> driversIterator = loadedDrivers.iterator();
/* Load these drivers, so that they can be instantiated...*/
try {
while (driversIterator.hasNext()) {
driversIterator.next();
}
} catch (Throwable t) {
// Do nothing
}
//...
}
接下来还要分别实现java.sql.Connection,java.sql.Statement和java.sql.ResultSet接口:
package org.littlestar.propsjdbc;
// import ...;
public class ConnectionImpl implements java.sql.Connection {
String dbPath = System.getProperty("user.dir");
public ConnectionImpl(String url) {
if (url != null) {
dbPath = url.trim().replaceFirst("jdbc:props:", "").trim();
}
}
@Override
public Statement createStatement() throws SQLException {
return new StatementImpl(dbPath);
}
// ... 其它接口实现省略
}
编写java.sql.Statement接口的实现:
package org.littlestar.propsjdbc;
// import ...;
public class StatementImpl implements java.sql.Statement {
String dbPath = "";
public StatementImpl(String path) {
dbPath = path;
}
@Override
public ResultSet executeQuery(String sql) throws SQLException {
String pattern = "(?i)SELECT.*?FROM";
String fileName = sql.replaceFirst(pattern, "").trim();
Properties props = new Properties();
String file = dbPath + File.separator + fileName;
try (BufferedReader reader = Files.newBufferedReader(Paths.get(file), StandardCharsets.UTF_8)) {
props.load(reader);
} catch (IOException e) {
throw new SQLException(e);
}
return new ResultSetImpl(props);
}
// ... 其它接口实现省略
}
编写java.sql.ResultSet实现:
package org.littlestar.propsjdbc;
//import ...
public class ResultSetImpl implements java.sql.ResultSet {
final Properties props;
Iterator<Entry<Object, Object>> iterator;
Entry<Object, Object> row;
public ResultSetImpl(Properties props) {
this.props = props;
iterator = props.entrySet().iterator();
}
@Override
public boolean next() throws SQLException {
boolean next = iterator.hasNext();
if (next) {
row = iterator.next();
}
return next;
}
@Override
public String getString(int columnIndex) throws SQLException {
if (row == null) {
return null;
}
if (columnIndex == 1) {
return row.getKey().toString();
} else if (columnIndex == 2) {
return row.getValue().toString();
} else {
return null;
}
}
// ... 其它接口实现省略
}
至此,jdbc驱动已经开发完毕,我们打包交给客户测试。Eclipse选择我们的项目,右键菜单选择"Export…“。在弹出的向导菜单中选择"JAR file”,然后点击下一步按钮。
点击结束按钮既可生成驱动的jar文件。交给用户测试。
测试如下。。。。先通过数据库管理工具"explorer.exe",创建一个"数据库":“D:\testcase\nbdb”,然后通过数据库开发工具“notepad.exe”创建一个表’table1’,内容如下:
名称=牛B数据库系统®
版本=高级企业版本(v24.4)
售价=60000000马内
供应商=白日梦股份有限公司
点击"保存"提交。接下来通过jdbc进行数据库访问:
public class Test {
public static void main(String[] args) throws SQLException {
String url = "jdbc:props:D:\\testcase\\nbdb";
try (Connection connection = DriverManager.getConnection(url);
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("select * from table1")) {
// System.out.println(connection.getClass().getCanonicalName());
// System.out.println(stmt.getClass().getCanonicalName());
// System.out.println(rs.getClass().getCanonicalName());
while (rs.next()) {
String key = rs.getString(1);
String value = rs.getString(2);
System.out.println(key + ": " + value);
}
}
}
}
// 程序执行结果如下:
售价: 60000000马内
名称: 牛B数据库系统®
版本: 高级企业版本(v24.4)
供应商: 白日梦股份有限公司
经过"客户"专家组评审,这套数据库系统测试符合预期,达到了业界领先水平,喜提6000w马内,实现人生财富自由。爽文至此结束。各位看官学废了吗?
最后附上完整代码(如果文件审核能过。。。),https://download.youkuaiyun.com/download/Li_Xiang_996/89071254