Ich habe mich gefragt, ob es möglich ist, eine serverlose RDB zu realisieren, aber ich denke, dass es ganz so ist, wenn ich CloudRun verwende. CloudRun kann jedoch kein JDBC sprechen, daher dachte ich, ich sollte meinen eigenen JDBC-Treiber erstellen und HTTP auf der Rückseite verwenden, also habe ich untersucht, wie es gemacht wird.
Überraschenderweise scheint es, dass der JDBC-Treiber einfach erstellt werden kann, daher habe ich vorerst versucht, die minimale Skeleton-Implementierung zu erstellen. Da es auf der Rückseite keine RDB gibt, werde ich im Grunde Folgendes machen, das nur ein Echo zurückgibt.
Lassen Sie uns zunächst eine Hauptklasse erstellen, die sowohl Kaninchen als auch Ecken testet und ausführt. Dies ist ein JDBC-Treiber, der von MyDriver und MyConnection erstellt wurde. Es ist eine einfache Implementierung, die nur bestätigt, dass der Rückgabewert MyConnection ist. Jetzt können Sie jedoch sehen, dass Ihr eigener JDBC-Treiber ordnungsgemäß aufgerufen wird.
github: https://github.com/koduki/jdbc-skeleton/blob/master/src/main/java/Main.java
var url = "jdbc:myjdbc://localhost:80/testdb";
Class.forName("cn.orz.pascal.jdbc.MyDriver");
try (var con = DriverManager.getConnection(url); var st = con.createStatement()) {
st.execute("INSERT DUMMY SQL");
try (var rs = st.executeQuery("SELECT DUMMY SQL")) {
while (rs.next()) {
System.out.println("rs[1]=" + rs.getString(1));
}
}
}
Das Ausführungsergebnis ist wie folgt.
jdbc uri: jdbc:myjdbc://localhost:80/testdb
execute sql: INSERT DUMMY SQL
execute sql: SELECT DUMMY SQL
rs[1]=a
rs[1]=e
rs[1]=h
MyResultSet close
MyStatement close
MyConnection close
Driver
Als nächstes kommt der JDBC-Treiber. Der Punkt ist der "statische" Initialisierer, der die Treiberregistrierung abschließt, wenn die Klasse mit "Class.forName" geladen wird.
Hier können Sie auch die JDBC-URL abrufen. In der tatsächlichen Implementierung scheint es üblich zu sein, die URL zu diesem Zeitpunkt zu analysieren und die Verbindungszielinformationen zusammenzustellen.
Im Beispielcode wird es mit "UnsupportedOperationException" implementiert, sofern nicht anders beschrieben. Sie müssen es bei Bedarf durch den tatsächlichen Code ersetzen.
github: https://github.com/koduki/jdbc-skeleton/blob/master/src/main/java/cn/orz/pascal/jdbc/MyDriver.java
package cn.orz.pascal.jdbc;
public class MyDriver implements Driver {
private static final String URI_PREFIX = "jdbc:myjdbc://";
static {
try {
java.sql.DriverManager.registerDriver(new MyDriver());
} catch (SQLException ex) {
throw new RuntimeException("Can't register driver!");
}
}
@Override
public Connection connect(String url, Properties info) throws SQLException {
if (!url.startsWith(URI_PREFIX)) {
return null;
}
return new MyConnection(url, info);
}
-Abkürzung-
Connection
Verbindung erstellt eine Anweisung. In der eigentlichen Implementierung wird die Verbindung in der Verbindungseinheit beibehalten, daher denke ich, dass Sie mit einem Konstruktor usw. zur Verbindung gehen werden.
github: https://github.com/koduki/jdbc-skeleton/blob/master/src/main/java/cn/orz/pascal/jdbc/MyConnection.java
package cn.orz.pascal.jdbc;
public class MyConnection implements Connection {
public MyConnection(String uri, Properties info) throws SQLException {
System.out.println("jdbc uri: " + uri);
}
@Override
public void close() throws SQLException {
System.out.println(this.getClass().getSimpleName() + " close");
}
@Override
public Statement createStatement() throws SQLException {
return new MyStatement();
}
-Abkürzung-
Statement
Anweisung verarbeitet Abfragen. Der SQL-Parser sollte hier aufgerufen werden. Da I / F nur eine Zeichenfolge übergibt, ist es übrigens möglich, problemlos eine andere Abfrage als SQL zu übergeben.
Der Dummy ordnet die Liste der Liste dem ResultSet zu und gibt sie zurück.
github: https://github.com/koduki/jdbc-skeleton/blob/master/src/main/java/cn/orz/pascal/jdbc/MyStatement.java
package cn.orz.pascal.jdbc;
public class MyStatement implements java.sql.Statement {
@Override
public boolean execute(String sql) throws SQLException {
System.out.println("execute sql: " + sql);
return true;
}
@Override
public ResultSet executeQuery(String sql) throws SQLException {
System.out.println("execute sql: " + sql);
var result = new MyResultSet(List.of(
List.of("a", "b", "c"),
List.of("e", "f", "g"),
List.of("h", "i", "j")
));
return result;
}
@Override
public void close() throws SQLException {
System.out.println(this.getClass().getSimpleName() + " close");
}
-Abkürzung-
ResultSet
ResultSet ist das Ergebnis der Abfrageausführung. Im Dummy wird es durch Umschließen des Iterators implementiert.
Im eigentlichen Code werden die eigentlichen Daten hier behandelt. Da die Datenbank jedoch im Allgemeinen groß ist, muss sie wie ein Iterator und nicht wie eine Liste implementiert werden.
github: https://github.com/koduki/jdbc-skeleton/blob/master/src/main/java/cn/orz/pascal/jdbc/MyResultSet.java
package cn.orz.pascal.jdbc;
public class MyResultSet implements java.sql.ResultSet {
private final Iterator<List<String>> itr;
private List<String> current;
public MyResultSet(List<List<String>> source) {
this.itr = source.iterator();
}
@Override
public String getString(int index) throws SQLException {
return current.get(index - 1);
}
@Override
public boolean next() throws SQLException {
var result = itr.hasNext();
if (result) {
current = itr.next();
}
return result;
}
-Abkürzung-
Als ich es ausprobierte, konnte ich den JDBC-Treiber einfacher implementieren als erwartet. Ich dachte, es wäre schwieriger, also bin ich ein bisschen verstimmt, aber es bedeutet, dass das I / F ordentlich implementiert ist.
Wenn Sie den JDBC-Treiber hacken können, können Sie SQL einbinden und in das Protokoll ausgeben, in Proxy konvertieren und in eine andere Datenbank überspringen oder ihn problemlos mit KVS oder einer anderen DB-Implementierung verbinden, einschließlich ORM wie JPA.
Da es viele APIs gibt, scheint es etwas Geduld zu erfordern, sie ernsthaft zu implementieren, aber wenn es sich um einen Typ handelt, der den eigentlichen JDBC umschließt, scheint es relativ einfach zu sein, ihn zu erstellen.
Dies scheint nützlich zu sein, daher scheint es gut, es in den Werkzeugkasten zu legen.
Dann viel Spaß beim Hacken!
Recommended Posts