From ed61bf6e61f96bdd5a7a745f90ba01f794fb4def Mon Sep 17 00:00:00 2001 From: rozhur Date: Fri, 11 Aug 2023 19:31:25 +0500 Subject: [PATCH] sql refactoring --- .../java/org/zhdev/sql/H2SqlConnection.java | 9 -- .../java/org/zhdev/sql/MySqlConnection.java | 9 -- .../main/java/org/zhdev/sql/SqlAdapter.java | 51 ----------- .../java/org/zhdev/sql/SqlConnection.java | 46 ---------- .../java/org/zhdev/sql/SqliteConnection.java | 9 -- .../zhdev/varioutil/sql/AbstractProvider.java | 26 ++++++ .../org/zhdev/varioutil/sql/H2Provider.java | 9 ++ .../zhdev/varioutil/sql/MysqlProvider.java | 9 ++ .../org/zhdev/varioutil/sql/NullProvider.java | 17 ++++ .../org/zhdev/varioutil/sql/SqlAdapter.java | 64 ++++++++++++++ .../{ => varioutil}/sql/SqlException.java | 2 +- .../zhdev/varioutil/sql/SqliteProvider.java | 9 ++ .../zhdev/{ => varioutil}/util/SqlUtils.java | 88 ++++++++++++++----- 13 files changed, 201 insertions(+), 147 deletions(-) delete mode 100644 db/src/main/java/org/zhdev/sql/H2SqlConnection.java delete mode 100644 db/src/main/java/org/zhdev/sql/MySqlConnection.java delete mode 100644 db/src/main/java/org/zhdev/sql/SqlAdapter.java delete mode 100644 db/src/main/java/org/zhdev/sql/SqlConnection.java delete mode 100644 db/src/main/java/org/zhdev/sql/SqliteConnection.java create mode 100644 db/src/main/java/org/zhdev/varioutil/sql/AbstractProvider.java create mode 100644 db/src/main/java/org/zhdev/varioutil/sql/H2Provider.java create mode 100644 db/src/main/java/org/zhdev/varioutil/sql/MysqlProvider.java create mode 100644 db/src/main/java/org/zhdev/varioutil/sql/NullProvider.java create mode 100644 db/src/main/java/org/zhdev/varioutil/sql/SqlAdapter.java rename db/src/main/java/org/zhdev/{ => varioutil}/sql/SqlException.java (90%) create mode 100644 db/src/main/java/org/zhdev/varioutil/sql/SqliteProvider.java rename db/src/main/java/org/zhdev/{ => varioutil}/util/SqlUtils.java (63%) diff --git a/db/src/main/java/org/zhdev/sql/H2SqlConnection.java b/db/src/main/java/org/zhdev/sql/H2SqlConnection.java deleted file mode 100644 index 6ed3c5a..0000000 --- a/db/src/main/java/org/zhdev/sql/H2SqlConnection.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.zhdev.sql; - -import org.zhdev.util.SqlUtils; - -public final class H2SqlConnection extends AbstractSqlConnection { - public H2SqlConnection(String path, String username, String password) { - super(SqlUtils.createH2Connection(path, username, password)); - } -} diff --git a/db/src/main/java/org/zhdev/sql/MySqlConnection.java b/db/src/main/java/org/zhdev/sql/MySqlConnection.java deleted file mode 100644 index f157ef1..0000000 --- a/db/src/main/java/org/zhdev/sql/MySqlConnection.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.zhdev.sql; - -import org.zhdev.util.SqlUtils; - -public final class MySqlConnection extends AbstractSqlConnection { - public MySqlConnection(String address, String dbname, String username, String password, boolean ssl) { - super(SqlUtils.createMySqlConnection(address, dbname, username, password, ssl)); - } -} diff --git a/db/src/main/java/org/zhdev/sql/SqlAdapter.java b/db/src/main/java/org/zhdev/sql/SqlAdapter.java deleted file mode 100644 index 5489836..0000000 --- a/db/src/main/java/org/zhdev/sql/SqlAdapter.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.zhdev.sql; - -import org.zhdev.util.CheckedFunction; - -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Objects; - -public final class SqlAdapter implements AutoCloseable { - private SqlConnection connection = SqlConnection.NOT_ESTABLISHED; - - public SqlConnection getConnection() { - return connection; - } - - public void setConnection(SqlConnection connection) { - Objects.requireNonNull(connection, "connection"); - this.connection = connection; - } - - public T prepareStatement(CheckedFunction function, String query, Object... args) throws SqlException { - try (PreparedStatement statement = connection.prepareStatement(query)) { - for (int i = 0, j = 1; i < args.length; i++, j++) { - statement.setObject(j, args[i]); - } - return function.apply(statement); - } catch (SQLException e) { - throw new SqlException(e); - } - } - - public T executeQuery(CheckedFunction function, String query, Object... args) throws SqlException { - return prepareStatement(statement -> { - try (ResultSet set = statement.executeQuery()) { - return function.apply(set); - } - }, query, args); - } - - public boolean isClosed() { - return connection.isClosed(); - } - - public void close() { - if (connection.isClosed()) { - connection.close(); - } - connection = SqlConnection.CLOSED; - } -} diff --git a/db/src/main/java/org/zhdev/sql/SqlConnection.java b/db/src/main/java/org/zhdev/sql/SqlConnection.java deleted file mode 100644 index 53ff976..0000000 --- a/db/src/main/java/org/zhdev/sql/SqlConnection.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.zhdev.sql; - -import java.sql.PreparedStatement; -import java.sql.SQLException; - -public interface SqlConnection extends AutoCloseable { - SqlConnection NOT_ESTABLISHED = new SqlConnection() { - @Override - public PreparedStatement prepareStatement(String query) { - throw new SqlException("Connection not established"); - } - - @Override - public boolean isClosed() { - return true; - } - - @Override - public void close() { - throw new SqlException("Connection not established"); - } - }; - SqlConnection CLOSED = new SqlConnection() { - @Override - public PreparedStatement prepareStatement(String query) { - throw new SqlException("Connection closed"); - } - - @Override - public boolean isClosed() { - return true; - } - - @Override - public void close() { - throw new SqlException("Connection closed"); - } - }; - - PreparedStatement prepareStatement(String query) throws SQLException; - - boolean isClosed(); - - @Override - void close(); -} diff --git a/db/src/main/java/org/zhdev/sql/SqliteConnection.java b/db/src/main/java/org/zhdev/sql/SqliteConnection.java deleted file mode 100644 index 4d3c111..0000000 --- a/db/src/main/java/org/zhdev/sql/SqliteConnection.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.zhdev.sql; - -import org.zhdev.util.SqlUtils; - -public class SqliteConnection extends AbstractSqlConnection { - public SqliteConnection(String path) { - super(SqlUtils.createSqliteConnection(path)); - } -} diff --git a/db/src/main/java/org/zhdev/varioutil/sql/AbstractProvider.java b/db/src/main/java/org/zhdev/varioutil/sql/AbstractProvider.java new file mode 100644 index 0000000..a0b83f6 --- /dev/null +++ b/db/src/main/java/org/zhdev/varioutil/sql/AbstractProvider.java @@ -0,0 +1,26 @@ +package org.zhdev.varioutil.sql; + +import java.sql.Connection; +import java.sql.SQLException; + +abstract class AbstractProvider implements ConnectionProvider { + private final Connection connection; + + AbstractProvider(Connection connection) { + this.connection = connection; + } + + @Override + public Connection getConnection() { + return connection; + } + + @Override + public boolean isClosed() { + try { + return connection.isClosed(); + } catch (SQLException e) { + throw new SqlException(e); + } + } +} diff --git a/db/src/main/java/org/zhdev/varioutil/sql/H2Provider.java b/db/src/main/java/org/zhdev/varioutil/sql/H2Provider.java new file mode 100644 index 0000000..cbee2a0 --- /dev/null +++ b/db/src/main/java/org/zhdev/varioutil/sql/H2Provider.java @@ -0,0 +1,9 @@ +package org.zhdev.varioutil.sql; + +import org.zhdev.varioutil.util.SqlUtils; + +public class H2Provider extends AbstractProvider { + public H2Provider(String path, String username, String password) { + super(SqlUtils.createH2Connection(path, username, password)); + } +} diff --git a/db/src/main/java/org/zhdev/varioutil/sql/MysqlProvider.java b/db/src/main/java/org/zhdev/varioutil/sql/MysqlProvider.java new file mode 100644 index 0000000..919f858 --- /dev/null +++ b/db/src/main/java/org/zhdev/varioutil/sql/MysqlProvider.java @@ -0,0 +1,9 @@ +package org.zhdev.varioutil.sql; + +import org.zhdev.varioutil.util.SqlUtils; + +public class MysqlProvider extends AbstractProvider { + public MysqlProvider(String address, String dbname, String username, String password, boolean ssl) { + super(SqlUtils.createMysqlConnection(address, dbname, username, password, ssl)); + } +} diff --git a/db/src/main/java/org/zhdev/varioutil/sql/NullProvider.java b/db/src/main/java/org/zhdev/varioutil/sql/NullProvider.java new file mode 100644 index 0000000..0b4c25b --- /dev/null +++ b/db/src/main/java/org/zhdev/varioutil/sql/NullProvider.java @@ -0,0 +1,17 @@ +package org.zhdev.varioutil.sql; + +import java.sql.Connection; + +class NullProvider implements ConnectionProvider { + private final String message; + + NullProvider(String message) { + this.message = message; + } + + + @Override + public Connection getConnection() { + throw new SqlException(message); + } +} diff --git a/db/src/main/java/org/zhdev/varioutil/sql/SqlAdapter.java b/db/src/main/java/org/zhdev/varioutil/sql/SqlAdapter.java new file mode 100644 index 0000000..9de1835 --- /dev/null +++ b/db/src/main/java/org/zhdev/varioutil/sql/SqlAdapter.java @@ -0,0 +1,64 @@ +package org.zhdev.varioutil.sql; + +import org.zhdev.varioutil.util.CheckedFunction; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Objects; + +public final class SqlAdapter implements AutoCloseable { + private ConnectionProvider provider = ConnectionProvider.NOT_ESTABLISHED; + + public void setProvider(ConnectionProvider provider) { + Objects.requireNonNull(provider, "provider"); + this.provider = provider; + } + + private static void applyArgs(PreparedStatement statement, Object[] args) throws SQLException { + for (int i = 0, j = 1; i < args.length; i++, j++) { + statement.setObject(j, args[i]); + } + } + + public T prepareStatement(CheckedFunction function, String query, Object... args) throws SqlException { + try (PreparedStatement statement = provider.getConnection().prepareStatement(query)) { + applyArgs(statement, args); + return function.apply(statement); + } catch (SQLException e) { + throw new SqlException(e); + } + } + + public T prepareStatement(int autoGeneratedKeys, CheckedFunction function, String query, Object... args) throws SqlException { + try (PreparedStatement statement = provider.getConnection().prepareStatement(query, autoGeneratedKeys)) { + applyArgs(statement, args); + return function.apply(statement); + } catch (SQLException e) { + throw new SqlException(e); + } + } + + public T executeQuery(CheckedFunction function, String query, Object... args) throws SqlException { + return prepareStatement(statement -> { + try (ResultSet set = statement.executeQuery()) { + return function.apply(set); + } + }, query, args); + } + + + + public boolean isClosed() { + return provider.isClosed(); + } + + public void close() { + if (!provider.isClosed()) { + provider.close(); + } + provider = ConnectionProvider.CLOSED; + } + +} diff --git a/db/src/main/java/org/zhdev/sql/SqlException.java b/db/src/main/java/org/zhdev/varioutil/sql/SqlException.java similarity index 90% rename from db/src/main/java/org/zhdev/sql/SqlException.java rename to db/src/main/java/org/zhdev/varioutil/sql/SqlException.java index 3745808..4eb0e4c 100644 --- a/db/src/main/java/org/zhdev/sql/SqlException.java +++ b/db/src/main/java/org/zhdev/varioutil/sql/SqlException.java @@ -1,4 +1,4 @@ -package org.zhdev.sql; +package org.zhdev.varioutil.sql; public class SqlException extends RuntimeException { public SqlException() { diff --git a/db/src/main/java/org/zhdev/varioutil/sql/SqliteProvider.java b/db/src/main/java/org/zhdev/varioutil/sql/SqliteProvider.java new file mode 100644 index 0000000..40c2e09 --- /dev/null +++ b/db/src/main/java/org/zhdev/varioutil/sql/SqliteProvider.java @@ -0,0 +1,9 @@ +package org.zhdev.varioutil.sql; + +import org.zhdev.varioutil.util.SqlUtils; + +public class SqliteProvider extends AbstractProvider { + public SqliteProvider(String path) { + super(SqlUtils.createSqliteConnection(path)); + } +} diff --git a/db/src/main/java/org/zhdev/util/SqlUtils.java b/db/src/main/java/org/zhdev/varioutil/util/SqlUtils.java similarity index 63% rename from db/src/main/java/org/zhdev/util/SqlUtils.java rename to db/src/main/java/org/zhdev/varioutil/util/SqlUtils.java index 8cef355..b5392c8 100644 --- a/db/src/main/java/org/zhdev/util/SqlUtils.java +++ b/db/src/main/java/org/zhdev/varioutil/util/SqlUtils.java @@ -1,35 +1,34 @@ -package org.zhdev.util; +package org.zhdev.varioutil.util; -import org.zhdev.sql.SqlException; +import org.zhdev.varioutil.sql.SqlException; -import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.sql.*; public class SqlUtils { public static final char[] ESCAPE_CHARS = {'%', '_', '[', ']', '^'}; - public static Connection createMySqlConnection(String address, String dbname, String username, String password, boolean ssl) throws SqlException { + private static boolean sqlite; + private static boolean h2; + private static boolean mysql; + + public static Connection createMysqlConnection(String address, String dbname, String username, String password, boolean ssl) throws SqlException { try { - try { - Class.forName("com.mysql.cj.jdbc.Driver"); - } catch (ClassNotFoundException e) { - Class.forName("com.mysql.jdbc.Driver"); - } if (!address.contains(":")) { address = address + ":3306"; } return DriverManager.getConnection("jdbc:mysql://" + address + '/' + dbname + "?useSSL=" + ssl, username, password); } catch (SQLException e) { throw new SqlException(e); - } catch (ClassNotFoundException e) { - throw new SqlException("No suitable driver"); } } public static Connection createH2Connection(String path, String username, String password) throws SqlException { try { - Class.forName("org.h2.Driver"); + DriverManager.registerDriver(new org.h2.Driver()); Connection connection; if (username != null) { connection = DriverManager.getConnection("jdbc:h2:./" + path + ";mode=MySQL;AUTO_SERVER=TRUE", username, password); @@ -37,29 +36,29 @@ public class SqlUtils { connection = DriverManager.getConnection("jdbc:h2:./" + path + ";mode=MySQL;AUTO_SERVER=TRUE", "sa", ""); } return connection; - } catch (ClassNotFoundException e) { + } catch (NoClassDefFoundError e) { throw new SqlException("No suitable driver"); } catch (SQLException e) { throw new SqlException(e); } } - public static Connection createSqliteConnection(String path) throws SqlException { - File file = new File(path); - if (!file.exists()) { - File parent = file.getParentFile(); - if (parent != null) { - parent.mkdirs(); - } + public static Connection createSqliteConnection(String pathname) throws SqlException { + Path path = Paths.get(pathname); + if (!Files.exists(path)) { + Path parent = path.getParent(); try { - file.createNewFile(); + if (parent != null) { + Files.createDirectories(parent); + } + Files.createFile(path); } catch (IOException e) { throw new SqlException(e); } } try { Class.forName("org.sqlite.JDBC"); - return DriverManager.getConnection("jdbc:sqlite:" + file); + return DriverManager.getConnection("jdbc:sqlite:" + path); } catch (ClassNotFoundException e) { throw new SqlException("No suitable driver"); } catch (SQLException e) { @@ -101,4 +100,49 @@ public class SqlUtils { public static String unescape(String str, String escape) { return StringUtils.unescape(str, escape, ESCAPE_CHARS); } + + private static void initializeH2() { + if (h2) { + return; + } + + try { + DriverManager.registerDriver(new org.h2.Driver()); + } catch (NoClassDefFoundError | SQLException ignored) {} + + h2 = true; + } + + private static void initializeMySql() { + if (mysql) { + return; + } + + try { + try { + DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver()); + } catch (NoClassDefFoundError e) { + DriverManager.registerDriver(new com.mysql.jdbc.Driver()); + } + } catch (NoClassDefFoundError | SQLException ignored) {} + + mysql = true; + } + + private static void initializeSqlite() { + if (sqlite) { + return; + } + + try { + DriverManager.registerDriver(new org.sqlite.JDBC()); + } catch (NoClassDefFoundError | SQLException ignored) {} + + sqlite = true; + } + + static { + initializeH2(); + initializeMySql(); + } }