package pro.husk; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.concurrent.CompletableFuture; /** * Abstract Database class, serves as a base for any connection method (MySQL, * SQLite, etc.) * * @author Huskehhh * @author tips48 * @author Ktar5 */ public abstract class Database { // Connection to the database protected Connection connection; /** * Creates a new Database */ protected Database() { this.connection = null; } /** * Checks if a connection is open with the database * * @return true if the connection is open * @throws SQLException if the connection cannot be checked */ private boolean checkConnection() throws SQLException { return connection != null && !connection.isClosed(); } /** * Gets the connection with the database * * @return Connection with the database, will initialise new connection if dead * @throws SQLException if cannot get a connection */ public abstract Connection getConnection() throws SQLException; /** * Closes the connection with the database * * @throws SQLException if the connection cannot be closed */ public void closeConnection() throws SQLException { connection.close(); } /** * Executes a SQL Query and returns a ResultSet * If the connection is closed, it will be opened * * @param query Query to be run * @return ResultSet object * @throws SQLException If the query cannot be executed */ public ResultSet query(String query) throws SQLException { if (!checkConnection()) { connection = getConnection(); } PreparedStatement statement = connection.prepareStatement(query); return statement.executeQuery(); } /** * Executes a SQL Query * If the connection is closed, it will be opened * * @param query Query to be run * @param consumer to pass ResultSet to * @throws SQLException If the query cannot be executed */ public void query(String query, SQLConsumer<ResultSet> consumer) throws SQLException { ResultSet resultSet = query(query); consumer.accept(resultSet); resultSet.close(); resultSet.getStatement().close(); } /** * Executes a SQL Query and returns a CompletableFuture of a ResultSet * If the connection is closed, it will be opened * * @param query Query to be run * @return CompletableFuture of ResultSet object * internally throws SQLException If the query cannot be executed */ public CompletableFuture<ResultSet> queryAsync(String query) { return CompletableFuture.supplyAsync(() -> { try { return query(query); } catch (SQLException e) { e.printStackTrace(); } return null; }); } /** * Executes an Update SQL Update * See {@link java.sql.PreparedStatement#executeUpdate()} * If the connection is closed, it will be opened * * @param update Update to be run * @return result code, see {@link java.sql.PreparedStatement#executeUpdate()} * @throws SQLException If the query cannot be executed */ public int update(String update) throws SQLException { if (!checkConnection()) { connection = getConnection(); } PreparedStatement statement = connection.prepareStatement(update); int result = statement.executeUpdate(); statement.close(); return result; } /** * Executes an SQL update asynchronously * * @param update Update to be run * @return result code, see {@link java.sql.PreparedStatement#executeUpdate()} * internally throws SQLException If the query cannot be executed * internally throws ClassNotFoundException If the driver cannot be found; see {@link #getConnection()} */ public CompletableFuture<Integer> updateAsync(String update) { return CompletableFuture.supplyAsync(() -> { int results = 0; try { results = update(update); } catch (SQLException e) { e.printStackTrace(); } return results; }); } }