mirror of
https://github.com/BentoBoxWorld/BentoBox.git
synced 2025-03-11 22:31:45 +01:00
Added PostgreSQL database type
https://github.com/BentoBoxWorld/BentoBox/issues/789
This commit is contained in:
parent
45c78fc7f2
commit
00ac8dd12a
@ -38,11 +38,11 @@ public class Settings implements ConfigObject {
|
|||||||
private boolean useEconomy = true;
|
private boolean useEconomy = true;
|
||||||
|
|
||||||
// Database
|
// Database
|
||||||
@ConfigComment("JSON, MYSQL, MARIADB (10.2.3+), MONGODB, SQLITE and YAML(deprecated).")
|
@ConfigComment("JSON, MYSQL, MARIADB (10.2.3+), MONGODB, SQLITE, POSTGRESQL and YAML(deprecated).")
|
||||||
@ConfigComment("Transition database options are:")
|
@ConfigComment("Transition database options are:")
|
||||||
@ConfigComment(" YAML2JSON, YAML2MARIADB, YAML2MYSQL, YAML2MONGODB, YAML2SQLITE")
|
@ConfigComment(" YAML2JSON, YAML2MARIADB, YAML2MYSQL, YAML2MONGODB, YAML2SQLITE")
|
||||||
@ConfigComment(" JSON2MARIADB, JSON2MYSQL, JSON2MONGODB, JSON2SQLITE")
|
@ConfigComment(" JSON2MARIADB, JSON2MYSQL, JSON2MONGODB, JSON2SQLITE, JSON2POSTGRESQL")
|
||||||
@ConfigComment(" MYSQL2JSON, MARIADB2JSON, MONGODB2JSON, SQLITE2JSON")
|
@ConfigComment(" MYSQL2JSON, MARIADB2JSON, MONGODB2JSON, SQLITE2JSON, POSTGRESQL2JSON")
|
||||||
@ConfigComment("If you need others, please make a feature request.")
|
@ConfigComment("If you need others, please make a feature request.")
|
||||||
@ConfigComment("Transition options enable migration from one database type to another. Use /bbox migrate.")
|
@ConfigComment("Transition options enable migration from one database type to another. Use /bbox migrate.")
|
||||||
@ConfigComment("YAML and JSON are file-based databases.")
|
@ConfigComment("YAML and JSON are file-based databases.")
|
||||||
|
@ -5,6 +5,7 @@ import world.bentobox.bentobox.database.json.JSONDatabase;
|
|||||||
import world.bentobox.bentobox.database.mariadb.MariaDBDatabase;
|
import world.bentobox.bentobox.database.mariadb.MariaDBDatabase;
|
||||||
import world.bentobox.bentobox.database.mongodb.MongoDBDatabase;
|
import world.bentobox.bentobox.database.mongodb.MongoDBDatabase;
|
||||||
import world.bentobox.bentobox.database.mysql.MySQLDatabase;
|
import world.bentobox.bentobox.database.mysql.MySQLDatabase;
|
||||||
|
import world.bentobox.bentobox.database.postgresql.PostgreSQLDatabase;
|
||||||
import world.bentobox.bentobox.database.sqlite.SQLiteDatabase;
|
import world.bentobox.bentobox.database.sqlite.SQLiteDatabase;
|
||||||
import world.bentobox.bentobox.database.transition.*;
|
import world.bentobox.bentobox.database.transition.*;
|
||||||
import world.bentobox.bentobox.database.yaml.YamlDatabase;
|
import world.bentobox.bentobox.database.yaml.YamlDatabase;
|
||||||
@ -89,6 +90,12 @@ public interface DatabaseSetup {
|
|||||||
*/
|
*/
|
||||||
JSON2SQLITE(new Json2SQLiteDatabase()),
|
JSON2SQLITE(new Json2SQLiteDatabase()),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transition database, from JSON to PostgreSQL
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
JSON2POSTGRESQL(new Json2PostgreSQLDatabase()),
|
||||||
|
|
||||||
MYSQL(new MySQLDatabase()),
|
MYSQL(new MySQLDatabase()),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,7 +131,18 @@ public interface DatabaseSetup {
|
|||||||
* Transition database, from SQLite to JSON
|
* Transition database, from SQLite to JSON
|
||||||
* @since 1.6.0
|
* @since 1.6.0
|
||||||
*/
|
*/
|
||||||
SQLITE2JSON(new SQLite2JsonDatabase());
|
SQLITE2JSON(new SQLite2JsonDatabase()),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
POSTGRESQL(new PostgreSQLDatabase()),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transition database, from PostgreSQL to JSON
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
POSTGRESQL2JSON(new PostgreSQL2JsonDatabase());
|
||||||
|
|
||||||
DatabaseSetup database;
|
DatabaseSetup database;
|
||||||
|
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package world.bentobox.bentobox.database.postgresql;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.BentoBox;
|
||||||
|
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
|
||||||
|
import world.bentobox.bentobox.database.DatabaseConnectionSettingsImpl;
|
||||||
|
import world.bentobox.bentobox.database.DatabaseSetup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 1.6.0
|
||||||
|
* @author Poslovitch
|
||||||
|
*/
|
||||||
|
public class PostgreSQLDatabase implements DatabaseSetup {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> AbstractDatabaseHandler<T> getHandler(Class<T> dataObjectClass) {
|
||||||
|
BentoBox plugin = BentoBox.getInstance();
|
||||||
|
return new PostgreSQLDatabaseHandler<>(plugin, dataObjectClass, new PostgreSQLDatabaseConnector(new DatabaseConnectionSettingsImpl(
|
||||||
|
plugin.getSettings().getDatabaseHost(),
|
||||||
|
plugin.getSettings().getDatabasePort(),
|
||||||
|
plugin.getSettings().getDatabaseName(),
|
||||||
|
plugin.getSettings().getDatabaseUsername(),
|
||||||
|
plugin.getSettings().getDatabasePassword()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package world.bentobox.bentobox.database.postgresql;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.eclipse.jdt.annotation.NonNull;
|
||||||
|
import world.bentobox.bentobox.database.DatabaseConnectionSettingsImpl;
|
||||||
|
import world.bentobox.bentobox.database.DatabaseConnector;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 1.6.0
|
||||||
|
* @author Poslovitch
|
||||||
|
*/
|
||||||
|
public class PostgreSQLDatabaseConnector implements DatabaseConnector {
|
||||||
|
|
||||||
|
private String connectionUrl;
|
||||||
|
private DatabaseConnectionSettingsImpl dbSettings;
|
||||||
|
private static Connection connection = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for PostgreSQL database connections using the settings provided
|
||||||
|
* @param dbSettings - database settings
|
||||||
|
*/
|
||||||
|
PostgreSQLDatabaseConnector(@NonNull DatabaseConnectionSettingsImpl dbSettings) {
|
||||||
|
this.dbSettings = dbSettings;
|
||||||
|
connectionUrl = "jdbc:postgresql://" + dbSettings.getHost() + ":" + dbSettings.getPort() + "/" + dbSettings.getDatabaseName()
|
||||||
|
+ "?autoReconnect=true&useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object createConnection() {
|
||||||
|
// Only make one connection to the database
|
||||||
|
if (connection == null) {
|
||||||
|
try {
|
||||||
|
connection = DriverManager.getConnection(connectionUrl, dbSettings.getUsername(), dbSettings.getPassword());
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Bukkit.getLogger().severe("Could not connect to the database! " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeConnection() {
|
||||||
|
if (connection != null) {
|
||||||
|
try {
|
||||||
|
connection.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Bukkit.getLogger().severe("Could not close PostgreSQL database connection");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getConnectionUrl() {
|
||||||
|
return connectionUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull String getUniqueId(String tableName) {
|
||||||
|
// Not used
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean uniqueIdExists(String tableName, String key) {
|
||||||
|
// Not used
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,273 @@
|
|||||||
|
package world.bentobox.bentobox.database.postgresql;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
import org.eclipse.jdt.annotation.NonNull;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import world.bentobox.bentobox.BentoBox;
|
||||||
|
import world.bentobox.bentobox.database.DatabaseConnector;
|
||||||
|
import world.bentobox.bentobox.database.json.AbstractJSONDatabaseHandler;
|
||||||
|
import world.bentobox.bentobox.database.objects.DataObject;
|
||||||
|
|
||||||
|
import java.beans.IntrospectionException;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
*
|
||||||
|
* @since 1.6.0
|
||||||
|
* @author tastybento, Poslovitch
|
||||||
|
*/
|
||||||
|
public class PostgreSQLDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
|
||||||
|
|
||||||
|
private static final String COULD_NOT_LOAD_OBJECTS = "Could not load objects ";
|
||||||
|
private static final String COULD_NOT_LOAD_OBJECT = "Could not load object ";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connection to the database
|
||||||
|
*/
|
||||||
|
private Connection connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FIFO queue for saves or deletions. Note that the assumption here is that most database objects will be held
|
||||||
|
* in memory because loading is not handled with this queue. That means that it is theoretically
|
||||||
|
* possible to load something before it has been saved. So, in general, load your objects and then
|
||||||
|
* save them async only when you do not need the data again immediately.
|
||||||
|
*/
|
||||||
|
private Queue<Runnable> processQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Async save task that runs repeatedly
|
||||||
|
*/
|
||||||
|
private BukkitTask asyncSaveTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param plugin
|
||||||
|
* @param type The type of the objects that should be created and filled with
|
||||||
|
* values from the database or inserted into the database
|
||||||
|
* @param databaseConnector Contains the settings to create a connection to the database
|
||||||
|
*/
|
||||||
|
protected PostgreSQLDatabaseHandler(BentoBox plugin, Class<T> type, DatabaseConnector databaseConnector) {
|
||||||
|
super(plugin, type, databaseConnector);
|
||||||
|
connection = (Connection) databaseConnector.createConnection();
|
||||||
|
if (connection == null) {
|
||||||
|
plugin.logError("Are the settings in config.yml correct?");
|
||||||
|
Bukkit.getPluginManager().disablePlugin(plugin);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Check if the table exists in the database and if not, create it
|
||||||
|
createSchema();
|
||||||
|
processQueue = new ConcurrentLinkedQueue<>();
|
||||||
|
if (plugin.isEnabled()) {
|
||||||
|
asyncSaveTask = Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||||
|
// Loop continuously
|
||||||
|
while (plugin.isEnabled() || !processQueue.isEmpty()) {
|
||||||
|
while (!processQueue.isEmpty()) {
|
||||||
|
processQueue.poll().run();
|
||||||
|
}
|
||||||
|
// Clear the queue and then sleep
|
||||||
|
try {
|
||||||
|
Thread.sleep(25);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
plugin.logError("Thread sleep error " + e.getMessage());
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Cancel
|
||||||
|
asyncSaveTask.cancel();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the table in the database if it doesn't exist already
|
||||||
|
*/
|
||||||
|
private void createSchema() {
|
||||||
|
String sql = "CREATE TABLE IF NOT EXISTS `" +
|
||||||
|
dataObject.getCanonicalName() +
|
||||||
|
"` (json JSON, uniqueId VARCHAR(255) GENERATED ALWAYS AS (json->\"$.uniqueId\"), UNIQUE INDEX i (uniqueId) )";
|
||||||
|
// Prepare and execute the database statements
|
||||||
|
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
|
||||||
|
pstmt.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
plugin.logError("Problem trying to create schema for data object " + dataObject.getCanonicalName() + " " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<T> loadObjects() throws InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, IntrospectionException, NoSuchMethodException {
|
||||||
|
try (Statement preparedStatement = connection.createStatement()) {
|
||||||
|
List<T> list = new ArrayList<>();
|
||||||
|
|
||||||
|
String sb = "SELECT `json` FROM `" +
|
||||||
|
dataObject.getCanonicalName() +
|
||||||
|
"`";
|
||||||
|
try (ResultSet resultSet = preparedStatement.executeQuery(sb)) {
|
||||||
|
// Load all the results
|
||||||
|
Gson gson = getGson();
|
||||||
|
while (resultSet.next()) {
|
||||||
|
String json = resultSet.getString("json");
|
||||||
|
if (json != null) {
|
||||||
|
try {
|
||||||
|
T gsonResult = gson.fromJson(json, dataObject);
|
||||||
|
if (gsonResult != null) {
|
||||||
|
list.add(gsonResult);
|
||||||
|
}
|
||||||
|
} catch (JsonSyntaxException ex) {
|
||||||
|
plugin.logError(COULD_NOT_LOAD_OBJECT + ex.getMessage());
|
||||||
|
plugin.logError(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.logError(COULD_NOT_LOAD_OBJECTS + e.getMessage());
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
plugin.logError(COULD_NOT_LOAD_OBJECTS + e.getMessage());
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public T loadObject(@NonNull String uniqueId) throws InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, IntrospectionException, NoSuchMethodException {
|
||||||
|
String sb = "SELECT `json` FROM `" + dataObject.getCanonicalName() + "` WHERE uniqueId = ? LIMIT 1";
|
||||||
|
try (PreparedStatement preparedStatement = connection.prepareStatement(sb)) {
|
||||||
|
// UniqueId needs to be placed in quotes
|
||||||
|
preparedStatement.setString(1, "\"" + uniqueId + "\"");
|
||||||
|
try (ResultSet resultSet = preparedStatement.executeQuery()) {
|
||||||
|
if (resultSet.next()) {
|
||||||
|
// If there is a result, we only want/need the first one
|
||||||
|
Gson gson = getGson();
|
||||||
|
return gson.fromJson(resultSet.getString("json"), dataObject);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.logError(COULD_NOT_LOAD_OBJECT + uniqueId + " " + e.getMessage());
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
plugin.logError(COULD_NOT_LOAD_OBJECT + uniqueId + " " + e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||||
|
// Null check
|
||||||
|
if (instance == null) {
|
||||||
|
plugin.logError("MySQL database request to store a null. ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(instance instanceof DataObject)) {
|
||||||
|
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String sb = "INSERT INTO " +
|
||||||
|
"`" +
|
||||||
|
dataObject.getCanonicalName() +
|
||||||
|
"` (json) VALUES (?) ON DUPLICATE KEY UPDATE json = ?";
|
||||||
|
|
||||||
|
Gson gson = getGson();
|
||||||
|
String toStore = gson.toJson(instance);
|
||||||
|
if (plugin.isEnabled()) {
|
||||||
|
// Async
|
||||||
|
processQueue.add(() -> store(instance, toStore, sb));
|
||||||
|
} else {
|
||||||
|
// Sync
|
||||||
|
store(instance, toStore, sb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void store(T instance, String toStore, String sb) {
|
||||||
|
try (PreparedStatement preparedStatement = connection.prepareStatement(sb)) {
|
||||||
|
preparedStatement.setString(1, toStore);
|
||||||
|
preparedStatement.setString(2, toStore);
|
||||||
|
preparedStatement.execute();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
plugin.logError("Could not save object " + instance.getClass().getName() + " " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
|
||||||
|
// Null check
|
||||||
|
if (instance == null) {
|
||||||
|
plugin.logError("MySQL database request to delete a null.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(instance instanceof DataObject)) {
|
||||||
|
plugin.logError("This class is not a DataObject: " + instance.getClass().getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Method getUniqueId = dataObject.getMethod("getUniqueId");
|
||||||
|
deleteID((String) getUniqueId.invoke(instance));
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.logError("Could not delete object " + instance.getClass().getName() + " " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void delete(String uniqueId) {
|
||||||
|
String sb = "DELETE FROM `" +
|
||||||
|
dataObject.getCanonicalName() +
|
||||||
|
"` WHERE uniqueId = ?";
|
||||||
|
try (PreparedStatement preparedStatement = connection.prepareStatement(sb)) {
|
||||||
|
// UniqueId needs to be placed in quotes
|
||||||
|
preparedStatement.setString(1, "\"" + uniqueId + "\"");
|
||||||
|
preparedStatement.execute();
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.logError("Could not delete object " + dataObject.getCanonicalName() + " " + uniqueId + " " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean objectExists(String uniqueId) {
|
||||||
|
// Create the query to see if this key exists
|
||||||
|
String query = "SELECT IF ( EXISTS( SELECT * FROM `" +
|
||||||
|
dataObject.getCanonicalName() +
|
||||||
|
"` WHERE `uniqueId` = ?), 1, 0)";
|
||||||
|
|
||||||
|
try (PreparedStatement preparedStatement = connection.prepareStatement(query)) {
|
||||||
|
// UniqueId needs to be placed in quotes
|
||||||
|
preparedStatement.setString(1, "\"" + uniqueId + "\"");
|
||||||
|
try (ResultSet resultSet = preparedStatement.executeQuery()) {
|
||||||
|
if (resultSet.next()) {
|
||||||
|
return resultSet.getBoolean(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
plugin.logError("Could not check if key exists in database! " + uniqueId + " " + e.getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteID(String uniqueId) {
|
||||||
|
if (plugin.isEnabled()) {
|
||||||
|
processQueue.add(() -> delete(uniqueId));
|
||||||
|
} else {
|
||||||
|
delete(uniqueId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
/**
|
||||||
|
* Contains PostgreSQL database managers.
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
package world.bentobox.bentobox.database.postgresql;
|
@ -0,0 +1,17 @@
|
|||||||
|
package world.bentobox.bentobox.database.transition;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
|
||||||
|
import world.bentobox.bentobox.database.DatabaseSetup;
|
||||||
|
import world.bentobox.bentobox.database.json.JSONDatabase;
|
||||||
|
import world.bentobox.bentobox.database.postgresql.PostgreSQLDatabase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Poslovitch
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
public class Json2PostgreSQLDatabase implements DatabaseSetup {
|
||||||
|
@Override
|
||||||
|
public <T> AbstractDatabaseHandler<T> getHandler(Class<T> dataObjectClass) {
|
||||||
|
return new TransitionDatabaseHandler<>(dataObjectClass, new JSONDatabase().getHandler(dataObjectClass), new PostgreSQLDatabase().getHandler(dataObjectClass));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package world.bentobox.bentobox.database.transition;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
|
||||||
|
import world.bentobox.bentobox.database.DatabaseSetup;
|
||||||
|
import world.bentobox.bentobox.database.json.JSONDatabase;
|
||||||
|
import world.bentobox.bentobox.database.postgresql.PostgreSQLDatabase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Poslovitch
|
||||||
|
* @since 1.6.0
|
||||||
|
*/
|
||||||
|
public class PostgreSQL2JsonDatabase implements DatabaseSetup {
|
||||||
|
@Override
|
||||||
|
public <T> AbstractDatabaseHandler<T> getHandler(Class<T> dataObjectClass) {
|
||||||
|
return new TransitionDatabaseHandler<>(dataObjectClass, new PostgreSQLDatabase().getHandler(dataObjectClass), new JSONDatabase().getHandler(dataObjectClass));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user