All Downloads are FREE. Search and download functionalities are using the official Maven repository.

me.deecaad.core.database.Database Maven / Gradle / Ivy

package me.deecaad.core.database;

import me.deecaad.core.MechanicsCore;
import me.deecaad.core.utils.LogLevel;
import org.bukkit.scheduler.BukkitRunnable;

import org.jetbrains.annotations.Nullable;
import java.sql.*;
import java.util.function.Consumer;

public abstract class Database {

    private final DatabaseType type;

    public Database(DatabaseType type) {
        this.type = type;
    }

    /**
     * @return the type of this database
     */
    public DatabaseType getType() {
        return type;
    }

    /**
     * Closes all given variables. This has to be called after every query.
     *
     * @param connection the connection used
     * @param statement the statement used
     * @param resultSet the result set used
     */
    public void close(@Nullable Connection connection, @Nullable Statement statement, @Nullable ResultSet resultSet) {
        if (resultSet != null)
            try {
                resultSet.close();
            } catch (SQLException e) {
                MechanicsCore.debug.log(LogLevel.ERROR, e);
            }
        if (statement != null)
            try {
                statement.close();
            } catch (SQLException e) {
                MechanicsCore.debug.log(LogLevel.ERROR, e);
            }
        if (connection != null)
            try {
                connection.close();
            } catch (SQLException e) {
                MechanicsCore.debug.log(LogLevel.ERROR, e);
            }
    }

    /**
     * Runs given SQL statement in async. Used to e.g. INSERT, UPDATE or DELETE.
     *
     * @param forceSync should only be true on reload and disable
     * @param sql the sql statement to run
     */
    public void executeUpdate(boolean forceSync, String... sql) {
        if (sql == null || sql.length == 0)
            throw new IllegalArgumentException("Empty statement");

        if (forceSync) {
            executeUpdate(sql);
            return;
        }

        new BukkitRunnable() {
            public void run() {
                executeUpdate(sql);
            }
        }.runTaskAsynchronously(MechanicsCore.getPlugin());
    }

    private void executeUpdate(String... sql) {
        if (sql.length == 1) {
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            try {
                connection = getConnection();
                preparedStatement = connection.prepareStatement(sql[0]);
                preparedStatement.executeUpdate();
            } catch (SQLException e) {
                MechanicsCore.debug.log(LogLevel.ERROR, e);
            } finally {
                close(connection, preparedStatement, null);
            }
            return;
        }

        // When there is multiple SQL statements use batches
        Connection connection = null;
        Statement statement = null;

        try {
            connection = getConnection();
            statement = connection.createStatement();

            // Disable auto commit
            connection.setAutoCommit(false);

            // Add batches
            for (String sqlStatement : sql) {
                statement.addBatch(sqlStatement);
            }

            // Execute batches
            statement.executeBatch();

            // Finally actually commit the changes when everything is done
            connection.commit();
            connection.setAutoCommit(true);
        } catch (SQLException e) {
            MechanicsCore.debug.log(LogLevel.ERROR, e);
        } finally {
            close(connection, statement, null);
        }
    }

    /**
     * Runs given SQL query in async. Used to SELECT.
     * 

* Keep in mind that the consumer is still ran in async. You should wrap the data first and then do * what you wish with it using sync task. * * @param sql the sql query to run * @param consumer the consumer for result set of query */ public void executeQuery(String sql, Consumer consumer) { if (sql == null || sql.isEmpty() || consumer == null) throw new IllegalArgumentException("Empty statement or null consumer"); new BukkitRunnable() { public void run() { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { connection = getConnection(); preparedStatement = connection.prepareStatement(sql); resultSet = preparedStatement.executeQuery(); consumer.accept(resultSet); } catch (SQLException e) { MechanicsCore.debug.log(LogLevel.ERROR, e); } finally { close(connection, preparedStatement, resultSet); } } }.runTaskAsynchronously(MechanicsCore.getPlugin()); } /** * Simple method to print the result set to console. Requires LogLevel.DEBUG * * @param rs the query result */ public void printResultSet(ResultSet rs) { try { ResultSetMetaData rsmd = rs.getMetaData(); int columnsNumber = rsmd.getColumnCount(); StringBuilder builder = new StringBuilder(); while (rs.next()) { for (int i = 1; i <= columnsNumber; i++) { builder.append(" | ").append(rs.getString(i)); } builder.append(System.lineSeparator()); } MechanicsCore.debug.log(LogLevel.DEBUG, builder.toString()); } catch (SQLException e) { MechanicsCore.debug.log(LogLevel.ERROR, e); } } /** * Allows getting connections to the database. When using MySQL this fetches one connection from the * pool. When using SQLite this creates new connection in most cases. * * @return one connection to the database */ public abstract Connection getConnection() throws SQLException; /** * Has to be called on when server disables or plugin is reloaded */ public abstract void close() throws SQLException; /** * @return whether this database is closed */ public abstract boolean isClosed(); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy