Je me suis demandé s'il serait possible de réaliser un RDB sans serveur, mais je pense que c'est tout à fait le cas si j'utilise CloudRun. Cependant, CloudRun ne peut pas parler JDBC, j'ai donc pensé que je devrais créer mon propre pilote JDBC et utiliser HTTP à l'arrière, alors j'ai étudié comment le faire.
Étonnamment, il semble que le pilote JDBC puisse être facilement créé, j'ai donc essayé de créer l'implémentation minimale du squelette pour le moment. Comme il n'y a pas de RDB à l'arrière, je vais essentiellement faire ce qui suit qui renvoie simplement un écho.
--Classe principale pour les tests
Tout d'abord, créons une classe principale qui teste et exécute à la fois les lapins et les coins. Il s'agit d'un pilote JDBC créé par MyDriver et MyConnection. C'est une implémentation simple qui confirme simplement que la valeur de retour est MyConnection, mais vous pouvez maintenant voir que votre propre pilote JDBC est appelé correctement.
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));
}
}
}
Le résultat de l'exécution est le suivant.
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
Vient ensuite le pilote JDBC.
Le point est l'initialiseur statique
, qui termine l'enregistrement du pilote lorsque la classe est chargée avec Class.forName
.
Vous pouvez également obtenir l'URL JDBC ici. Dans l'implémentation réelle, il semble qu'il soit courant d'analyser l'URL à ce moment et d'assembler les informations de destination de connexion.
Dans l'exemple de code, il est implémenté avec ʻUnsupportedOperationException` sauf là où il est décrit. Vous devez le remplacer par le code réel si nécessaire.
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);
}
-Abréviation-
Connection
Connection crée une déclaration. Dans l'implémentation réelle, la connexion est maintenue dans les unités de connexion, donc je pense que vous irez à la connexion avec un constructeur etc.
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();
}
-Abréviation-
Statement
La déclaration traite les requêtes. L'analyseur SQL doit être appelé ici. Au fait, comme I / F ne fait que passer une chaîne de caractères, il est possible de passer une requête autre que SQL sans aucun problème.
Le mannequin mappe la liste de liste au ResultSet et le renvoie.
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");
}
-Abréviation-
ResultSet
ResultSet est le résultat de l'exécution de la requête. Dans le mannequin, il est implémenté en enveloppant l'itérateur.
Dans le code actuel, les données réelles seront traitées ici, mais comme la base de données est généralement volumineuse, il sera nécessaire de l'implémenter comme un itérateur plutôt que comme une liste.
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;
}
-Abréviation-
Eh bien, quand je l'ai essayé, j'ai pu implémenter le pilote JDBC plus facilement que prévu. Je pensais que ce serait plus difficile, donc je suis un peu désaccordé, mais cela signifie que l'I / F est bien implémenté.
Si vous pouvez pirater le pilote JDBC, vous pouvez raccorder SQL et le sortir dans le journal, le convertir en Proxy et l'ignorer dans une autre base de données, ou le connecter à KVS ou à une autre implémentation de base de données sans difficulté, y compris ORM tel que JPA.
Comme il existe de nombreuses API, il semble qu'il faudra un peu de patience pour l'implémenter sérieusement, mais s'il s'agit d'un type qui encapsule le JDBC réel, cela semble relativement facile à faire.
Cela semble utile, il semble donc bon de le mettre dans la boîte à outils.
Alors bon piratage!
Recommended Posts