mirror of
https://github.com/BG-Software-LLC/WildLoaders.git
synced 2024-11-14 10:35:20 +01:00
Implemented the queue-based database interaction system
This commit is contained in:
parent
689f049a8b
commit
ea387cff58
@ -10,6 +10,7 @@ import com.bgsoftware.wildloaders.listeners.BlocksListener;
|
||||
import com.bgsoftware.wildloaders.listeners.ChunksListener;
|
||||
import com.bgsoftware.wildloaders.metrics.Metrics;
|
||||
import com.bgsoftware.wildloaders.nms.NMSAdapter;
|
||||
import com.bgsoftware.wildloaders.utils.database.Database;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public final class WildLoadersPlugin extends JavaPlugin implements WildLoaders {
|
||||
@ -58,7 +59,7 @@ public final class WildLoadersPlugin extends JavaPlugin implements WildLoaders {
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
dataHandler.saveDatabase();
|
||||
Database.stop();
|
||||
loadersHandler.removeChunkLoaders();
|
||||
npcHandler.killAllNPCs();
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package com.bgsoftware.wildloaders.command;
|
||||
import com.bgsoftware.wildloaders.Locale;
|
||||
import com.bgsoftware.wildloaders.WildLoadersPlugin;
|
||||
import com.bgsoftware.wildloaders.command.commands.CmdGive;
|
||||
import com.bgsoftware.wildloaders.command.commands.CmdSave;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
@ -19,7 +18,6 @@ public final class CommandsHandler implements CommandExecutor, TabCompleter {
|
||||
public CommandsHandler(WildLoadersPlugin plugin){
|
||||
this.plugin = plugin;
|
||||
subCommands.add(new CmdGive());
|
||||
subCommands.add(new CmdSave());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,59 +0,0 @@
|
||||
package com.bgsoftware.wildloaders.command.commands;
|
||||
|
||||
import com.bgsoftware.wildloaders.WildLoadersPlugin;
|
||||
import com.bgsoftware.wildloaders.command.ICommand;
|
||||
import com.bgsoftware.wildloaders.utils.threads.Executor;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class CmdSave implements ICommand {
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "save";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "loader save";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermission() {
|
||||
return "wildloaders.save";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Save all the chunk-loaders into the database.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinArgs() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxArgs() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(WildLoadersPlugin plugin, CommandSender sender, String[] args) {
|
||||
Executor.data(() -> {
|
||||
long startTime = System.currentTimeMillis();
|
||||
sender.sendMessage(ChatColor.YELLOW + "Saving all chunk loaders...");
|
||||
plugin.getDataHandler().saveDatabase();
|
||||
sender.sendMessage(ChatColor.YELLOW + "Saving chunk loaders done! (Took " + (System.currentTimeMillis() - startTime) + "ms)");
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> tabComplete(WildLoadersPlugin plugin, CommandSender sender, String[] args) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
@ -1,22 +1,14 @@
|
||||
package com.bgsoftware.wildloaders.handlers;
|
||||
|
||||
import com.bgsoftware.wildloaders.WildLoadersPlugin;
|
||||
import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
|
||||
import com.bgsoftware.wildloaders.api.loaders.LoaderData;
|
||||
import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC;
|
||||
import com.bgsoftware.wildloaders.loaders.WChunkLoader;
|
||||
import com.bgsoftware.wildloaders.npc.NPCIdentifier;
|
||||
import com.bgsoftware.wildloaders.utils.database.Query;
|
||||
import com.bgsoftware.wildloaders.utils.database.SQLHelper;
|
||||
import com.bgsoftware.wildloaders.utils.database.StatementHolder;
|
||||
import com.bgsoftware.wildloaders.utils.database.Database;
|
||||
import com.bgsoftware.wildloaders.utils.locations.LocationUtils;
|
||||
import com.bgsoftware.wildloaders.utils.threads.Executor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -28,7 +20,7 @@ public final class DataHandler {
|
||||
this.plugin = plugin;
|
||||
Executor.sync(() -> {
|
||||
try {
|
||||
SQLHelper.init(new File(plugin.getDataFolder(), "database.db"));
|
||||
Database.start(new File(plugin.getDataFolder(), "database.db"));
|
||||
loadDatabase();
|
||||
}catch (Exception ex){
|
||||
ex.printStackTrace();
|
||||
@ -38,8 +30,8 @@ public final class DataHandler {
|
||||
}
|
||||
|
||||
public void loadDatabase(){
|
||||
SQLHelper.executeUpdate("CREATE TABLE IF NOT EXISTS npc_identifiers (location TEXT NOT NULL PRIMARY KEY, uuid TEXT NOT NULL);");
|
||||
SQLHelper.executeQuery("SELECT * FROM npc_identifiers;", resultSet -> {
|
||||
Database.executeUpdate("CREATE TABLE IF NOT EXISTS npc_identifiers (location TEXT NOT NULL PRIMARY KEY, uuid TEXT NOT NULL);");
|
||||
Database.executeQuery("SELECT * FROM npc_identifiers;", resultSet -> {
|
||||
while (resultSet.next()) {
|
||||
Location location = LocationUtils.getLocation(resultSet.getString("location"));
|
||||
UUID uuid = UUID.fromString(resultSet.getString("uuid"));
|
||||
@ -47,8 +39,8 @@ public final class DataHandler {
|
||||
}
|
||||
});
|
||||
|
||||
SQLHelper.executeUpdate("CREATE TABLE IF NOT EXISTS chunk_loaders (location TEXT NOT NULL PRIMARY KEY, placer TEXT NOT NULL, loader_data TEXT NOT NULL, timeLeft BIGINT NOT NULL);");
|
||||
SQLHelper.executeQuery("SELECT * FROM chunk_loaders;", resultSet -> {
|
||||
Database.executeUpdate("CREATE TABLE IF NOT EXISTS chunk_loaders (location TEXT NOT NULL PRIMARY KEY, placer TEXT NOT NULL, loader_data TEXT NOT NULL, timeLeft BIGINT NOT NULL);");
|
||||
Database.executeQuery("SELECT * FROM chunk_loaders;", resultSet -> {
|
||||
while(resultSet.next()){
|
||||
Location location = LocationUtils.getLocation(resultSet.getString("location"));
|
||||
UUID placer = UUID.fromString(resultSet.getString("placer"));
|
||||
@ -68,54 +60,4 @@ public final class DataHandler {
|
||||
});
|
||||
}
|
||||
|
||||
public void saveDatabase(){
|
||||
List<ChunkLoader> chunkLoaderList = plugin.getLoaders().getChunkLoaders();
|
||||
Map<NPCIdentifier, ChunkLoaderNPC> chunkLoaderNPCList = plugin.getNPCs().getNPCs();
|
||||
|
||||
{
|
||||
StatementHolder chunkLoadersHolder = Query.INSERT_CHUNK_LOADER.getStatementHolder();
|
||||
chunkLoadersHolder.prepareBatch();
|
||||
chunkLoaderList.stream().filter(chunkLoader -> chunkLoader.getTimeLeft() > 0).forEach(chunkLoader ->
|
||||
((WChunkLoader) chunkLoader).updateInsertStatement(chunkLoadersHolder).addBatch());
|
||||
chunkLoadersHolder.execute(false);
|
||||
}
|
||||
|
||||
{
|
||||
StatementHolder chunkLoadersHolder = Query.DELETE_CHUNK_LOADER.getStatementHolder();
|
||||
chunkLoadersHolder.prepareBatch();
|
||||
chunkLoaderList.stream().filter(chunkLoader -> chunkLoader.getTimeLeft() <= 0).forEach(chunkLoader ->
|
||||
chunkLoadersHolder.setLocation(chunkLoader.getLocation()).addBatch());
|
||||
chunkLoadersHolder.execute(false);
|
||||
}
|
||||
|
||||
{
|
||||
StatementHolder npcIdentifierHolder = Query.INSERT_NPC_IDENTIFIER.getStatementHolder();
|
||||
npcIdentifierHolder.prepareBatch();
|
||||
chunkLoaderNPCList.forEach((identifier, npc) -> npcIdentifierHolder
|
||||
.setLocation(identifier.getSpawnLocation()).setString(npc.getUniqueId().toString()).addBatch());
|
||||
npcIdentifierHolder.execute(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void saveChunkLoadersTimes(){
|
||||
List<ChunkLoader> chunkLoaderList = plugin.getLoaders().getChunkLoaders();
|
||||
|
||||
{
|
||||
StatementHolder chunkLoadersHolder = Query.UPDATE_CHUNK_LOADER_TIME_LEFT.getStatementHolder();
|
||||
chunkLoadersHolder.prepareBatch();
|
||||
chunkLoaderList.stream().filter(chunkLoader -> chunkLoader.getTimeLeft() > 0).forEach(chunkLoader ->
|
||||
chunkLoadersHolder.setLong(chunkLoader.getTimeLeft()).setLocation(chunkLoader.getLocation()).addBatch());
|
||||
chunkLoadersHolder.execute(false);
|
||||
}
|
||||
|
||||
{
|
||||
StatementHolder chunkLoadersHolder = Query.DELETE_CHUNK_LOADER.getStatementHolder();
|
||||
chunkLoadersHolder.prepareBatch();
|
||||
chunkLoaderList.stream().filter(chunkLoader -> chunkLoader.getTimeLeft() <= 0).forEach(chunkLoader ->
|
||||
chunkLoadersHolder.setLocation(chunkLoader.getLocation()).addBatch());
|
||||
chunkLoadersHolder.execute(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import com.bgsoftware.wildloaders.loaders.WLoaderData;
|
||||
import com.bgsoftware.wildloaders.utils.chunks.ChunkPosition;
|
||||
import com.bgsoftware.wildloaders.utils.database.Query;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -24,8 +23,6 @@ import java.util.UUID;
|
||||
|
||||
public final class LoadersHandler implements LoadersManager {
|
||||
|
||||
private static final long TIMERS_UPDATE_INTERVAL = 300L;
|
||||
|
||||
private final Map<Location, ChunkLoader> chunkLoaders = Maps.newConcurrentMap();
|
||||
private final Map<ChunkPosition, ChunkLoader> chunkLoadersByChunks = Maps.newConcurrentMap();
|
||||
private final Map<String, LoaderData> loadersData = Maps.newConcurrentMap();
|
||||
@ -33,8 +30,6 @@ public final class LoadersHandler implements LoadersManager {
|
||||
|
||||
public LoadersHandler(WildLoadersPlugin plugin){
|
||||
this.plugin = plugin;
|
||||
|
||||
Bukkit.getScheduler().runTaskTimer(plugin, plugin.getDataHandler()::saveChunkLoadersTimes, TIMERS_UPDATE_INTERVAL, TIMERS_UPDATE_INTERVAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -65,7 +60,14 @@ public final class LoadersHandler implements LoadersManager {
|
||||
@Override
|
||||
public ChunkLoader addChunkLoader(LoaderData loaderData, Player whoPlaced, Location location, long timeLeft) {
|
||||
WChunkLoader chunkLoader = addChunkLoader(loaderData, whoPlaced.getUniqueId(), location, timeLeft);
|
||||
chunkLoader.updateInsertStatement(Query.INSERT_CHUNK_LOADER.getStatementHolder()).execute(true);
|
||||
|
||||
Query.INSERT_CHUNK_LOADER.insertParameters()
|
||||
.setLocation(location)
|
||||
.setObject(whoPlaced.getUniqueId().toString())
|
||||
.setObject(loaderData.getName())
|
||||
.setObject(timeLeft)
|
||||
.queue(location);
|
||||
|
||||
return chunkLoader;
|
||||
}
|
||||
|
||||
@ -74,7 +76,6 @@ public final class LoadersHandler implements LoadersManager {
|
||||
chunkLoaders.put(location, chunkLoader);
|
||||
chunkLoadersByChunks.put(ChunkPosition.of(location), chunkLoader);
|
||||
plugin.getNPCs().createNPC(location);
|
||||
System.out.println("Adding chunk loader for " + location);
|
||||
return chunkLoader;
|
||||
}
|
||||
|
||||
@ -85,9 +86,9 @@ public final class LoadersHandler implements LoadersManager {
|
||||
chunkLoadersByChunks.remove(ChunkPosition.of(location));
|
||||
chunkLoader.getNPC().ifPresent(npc -> plugin.getNPCs().killNPC(npc));
|
||||
|
||||
Query.DELETE_CHUNK_LOADER.getStatementHolder()
|
||||
.setLocation(location)
|
||||
.execute(true);
|
||||
Query.DELETE_CHUNK_LOADER.insertParameters()
|
||||
.setObject(location)
|
||||
.queue(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,9 +51,9 @@ public final class NPCHandler implements NPCManager {
|
||||
|
||||
npcUUIDs.remove(identifier);
|
||||
|
||||
Query.DELETE_NPC_IDENTIFIER.getStatementHolder()
|
||||
Query.DELETE_NPC_IDENTIFIER.insertParameters()
|
||||
.setLocation(identifier.getSpawnLocation())
|
||||
.execute(true);
|
||||
.queue(npc.getUniqueId());
|
||||
|
||||
npc.die();
|
||||
}
|
||||
@ -88,10 +88,10 @@ public final class NPCHandler implements NPCManager {
|
||||
|
||||
npcUUIDs.put(identifier, uuid);
|
||||
|
||||
Query.INSERT_NPC_IDENTIFIER.getStatementHolder()
|
||||
Query.INSERT_NPC_IDENTIFIER.insertParameters()
|
||||
.setLocation(identifier.getSpawnLocation())
|
||||
.setString(uuid.toString())
|
||||
.execute(true);
|
||||
.setObject(uuid.toString())
|
||||
.queue(uuid);
|
||||
|
||||
return uuid;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import com.bgsoftware.wildloaders.WildLoadersPlugin;
|
||||
import com.bgsoftware.wildloaders.api.loaders.ChunkLoader;
|
||||
import com.bgsoftware.wildloaders.api.loaders.LoaderData;
|
||||
import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC;
|
||||
import com.bgsoftware.wildloaders.utils.database.StatementHolder;
|
||||
import com.bgsoftware.wildloaders.utils.database.Query;
|
||||
import com.bgsoftware.wildloaders.utils.threads.Executor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@ -60,6 +60,12 @@ public final class WChunkLoader implements ChunkLoader {
|
||||
if(timeLeft < 0) {
|
||||
remove();
|
||||
}
|
||||
else if(timeLeft > 0 && timeLeft % 10 == 0){
|
||||
Query.UPDATE_CHUNK_LOADER_TIME_LEFT.insertParameters()
|
||||
.setObject(timeLeft)
|
||||
.setLocation(location)
|
||||
.queue(location);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -91,13 +97,4 @@ public final class WChunkLoader implements ChunkLoader {
|
||||
return plugin.getNMSAdapter().setTag(itemStack, "loader-time", getTimeLeft());
|
||||
}
|
||||
|
||||
public StatementHolder updateInsertStatement(StatementHolder statementHolder){
|
||||
statementHolder.setLocation(getLocation())
|
||||
.setString(whoPlaced.toString())
|
||||
.setString(getLoaderData().getName())
|
||||
.setLong(getTimeLeft());
|
||||
|
||||
return statementHolder;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,82 @@
|
||||
package com.bgsoftware.wildloaders.utils.database;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public final class Database {
|
||||
|
||||
private static final int CONNECTION_TIMEOUT = 900;
|
||||
|
||||
private static String dbFilePath = "";
|
||||
|
||||
private static Connection connection = null;
|
||||
private static long lastConnectionCreation = 0;
|
||||
|
||||
private Database(){}
|
||||
|
||||
public static void start(File databaseFile){
|
||||
Database.dbFilePath = databaseFile.getAbsolutePath().replace("\\", "/");
|
||||
DatabaseQueue.start();
|
||||
}
|
||||
|
||||
public static void stop(){
|
||||
try {
|
||||
DatabaseQueue.stop();
|
||||
if(connection != null)
|
||||
connection.close();
|
||||
}catch (Exception ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void executeQuery(String statement, DatabaseConsumer<ResultSet> callback){
|
||||
initializeConnection();
|
||||
try(PreparedStatement preparedStatement = connection.prepareStatement(statement); ResultSet resultSet = preparedStatement.executeQuery()){
|
||||
callback.accept(resultSet);
|
||||
}catch(SQLException ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void executeUpdate(String statement){
|
||||
initializeConnection();
|
||||
try(PreparedStatement preparedStatement = connection.prepareStatement(statement)){
|
||||
preparedStatement.executeUpdate();
|
||||
}catch(SQLException ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Connection getConnection() {
|
||||
initializeConnection();
|
||||
return connection;
|
||||
}
|
||||
|
||||
private static void initializeConnection(){
|
||||
try {
|
||||
long currentTime = System.currentTimeMillis() / 1000;
|
||||
if(connection == null || currentTime - lastConnectionCreation > CONNECTION_TIMEOUT) {
|
||||
if(connection != null)
|
||||
connection.close();
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
String sqlURL = "jdbc:sqlite:" + dbFilePath;
|
||||
connection = DriverManager.getConnection(sqlURL);
|
||||
lastConnectionCreation = currentTime;
|
||||
}
|
||||
}catch (Exception ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public interface DatabaseConsumer<T>{
|
||||
|
||||
void accept(T t) throws SQLException;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package com.bgsoftware.wildloaders.utils.database;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public final class DatabaseQueue {
|
||||
|
||||
private static final ScheduledExecutorService queueService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder().setNameFormat("WildStacker Database Thread").build());
|
||||
private static final long QUEUE_INTERVAL = 60;
|
||||
|
||||
private static final Map<Integer, QueryParameters> queuedCalls = new ConcurrentHashMap<>();
|
||||
private static final Map<Query, Map<Object, Integer>> alreadyObjectsCalled = new ConcurrentHashMap<>();
|
||||
private static final AtomicInteger currentIndex = new AtomicInteger(0);
|
||||
|
||||
public static void queue(Object caller, QueryParameters parameters){
|
||||
Map<Object, Integer> queryCalls = alreadyObjectsCalled.computeIfAbsent(parameters.getQuery(), q -> new ConcurrentHashMap<>());
|
||||
Integer existingParametersIndex = queryCalls.get(caller);
|
||||
|
||||
if(existingParametersIndex != null)
|
||||
queuedCalls.remove(existingParametersIndex);
|
||||
|
||||
int currentIndex = DatabaseQueue.currentIndex.getAndIncrement();
|
||||
|
||||
queuedCalls.put(currentIndex, parameters);
|
||||
queryCalls.put(caller, currentIndex);
|
||||
}
|
||||
|
||||
static void start() {
|
||||
queueService.scheduleAtFixedRate(DatabaseQueue::processQueue, QUEUE_INTERVAL, QUEUE_INTERVAL, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
static void stop(){
|
||||
// Stopping the queue timer, and calling the process queue manually
|
||||
queueService.shutdownNow();
|
||||
processQueue();
|
||||
}
|
||||
|
||||
private static void processQueue(){
|
||||
int currentIndex = DatabaseQueue.currentIndex.getAndSet(0);
|
||||
if(currentIndex > 0) {
|
||||
Map<Query, PreparedStatement> preparedStatementMap = new EnumMap<>(Query.class);
|
||||
Connection connection = Database.getConnection();
|
||||
|
||||
for(int i = 0; i < currentIndex; i++){
|
||||
try {
|
||||
QueryParameters parameters = queuedCalls.get(i);
|
||||
|
||||
if (parameters == null)
|
||||
continue;
|
||||
|
||||
PreparedStatement preparedStatement = preparedStatementMap.computeIfAbsent(parameters.getQuery(), q -> {
|
||||
try {
|
||||
return connection.prepareStatement(q.getStatement());
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
if (preparedStatement != null) {
|
||||
parameters.executeQuery(preparedStatement);
|
||||
preparedStatement.executeUpdate();
|
||||
preparedStatement.clearParameters();
|
||||
}
|
||||
}catch (Exception ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
preparedStatementMap.values().forEach(preparedStatement -> {
|
||||
try{
|
||||
preparedStatement.close();
|
||||
}catch (Exception ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -2,24 +2,31 @@ package com.bgsoftware.wildloaders.utils.database;
|
||||
|
||||
public enum Query {
|
||||
|
||||
UPDATE_CHUNK_LOADER_TIME_LEFT("UPDATE chunk_loaders SET timeLeft=? WHERE location=?;"),
|
||||
INSERT_CHUNK_LOADER("REPLACE INTO chunk_loaders(location, placer, loader_data, timeLeft) VALUES(?,?,?,?);"),
|
||||
DELETE_CHUNK_LOADER("DELETE FROM chunk_loaders WHERE location=?;"),
|
||||
UPDATE_CHUNK_LOADER_TIME_LEFT("UPDATE chunk_loaders SET timeLeft=? WHERE location=?;", 2),
|
||||
INSERT_CHUNK_LOADER("REPLACE INTO chunk_loaders(location, placer, loader_data, timeLeft) VALUES(?,?,?,?);", 4),
|
||||
DELETE_CHUNK_LOADER("DELETE FROM chunk_loaders WHERE location=?;", 1),
|
||||
|
||||
INSERT_NPC_IDENTIFIER("REPLACE INTO npc_identifiers(location, uuid) VALUES(?,?);"),
|
||||
DELETE_NPC_IDENTIFIER("DELETE FROM npc_identifiers WHERE location=?;");
|
||||
INSERT_NPC_IDENTIFIER("REPLACE INTO npc_identifiers(location, uuid) VALUES(?,?);", 2),
|
||||
DELETE_NPC_IDENTIFIER("DELETE FROM npc_identifiers WHERE location=?;", 1);
|
||||
|
||||
private final String query;
|
||||
private final int parametersCount;
|
||||
|
||||
Query(String query) {
|
||||
Query(String query, int parametersCount) {
|
||||
this.query = query;
|
||||
this.parametersCount = parametersCount;
|
||||
}
|
||||
|
||||
public String getStatement(){
|
||||
return query;
|
||||
}
|
||||
|
||||
public StatementHolder getStatementHolder(){
|
||||
return new StatementHolder(this);
|
||||
int getParametersCount() {
|
||||
return parametersCount;
|
||||
}
|
||||
|
||||
public QueryParameters insertParameters(){
|
||||
return new QueryParameters(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
package com.bgsoftware.wildloaders.utils.database;
|
||||
|
||||
import com.bgsoftware.wildloaders.WildLoadersPlugin;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class QueryParameters {
|
||||
|
||||
private static final WildLoadersPlugin plugin = WildLoadersPlugin.getPlugin();
|
||||
|
||||
private final Query query;
|
||||
private final List<Object> parameters;
|
||||
|
||||
public QueryParameters(Query query){
|
||||
this.query = query;
|
||||
this.parameters = new ArrayList<>(query.getParametersCount());
|
||||
}
|
||||
|
||||
public Query getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public void executeQuery(PreparedStatement preparedStatement) throws SQLException {
|
||||
for(int i = 0; i < parameters.size(); i++)
|
||||
preparedStatement.setObject(i + 1, parameters.get(i));
|
||||
}
|
||||
|
||||
public void queue(Object caller){
|
||||
DatabaseQueue.queue(caller, this);
|
||||
}
|
||||
|
||||
public QueryParameters setLocation(Location loc){
|
||||
return setObject(loc.getWorld().getName() + "," + loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ());
|
||||
}
|
||||
|
||||
public QueryParameters setObject(Object object){
|
||||
parameters.add(object);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "QueryParameters{" +
|
||||
"query=" + query +
|
||||
", parameters=" + parameters +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
package com.bgsoftware.wildloaders.utils.database;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public final class SQLHelper {
|
||||
|
||||
private static final Object mutex = new Object();
|
||||
private static Connection conn;
|
||||
|
||||
private SQLHelper(){}
|
||||
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
public static void init(File file) throws ClassNotFoundException, SQLException {
|
||||
if(!file.exists()){
|
||||
try {
|
||||
file.getParentFile().mkdirs();
|
||||
file.createNewFile();
|
||||
}catch(Exception ex){
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
String sqlURL = "jdbc:sqlite:" + file.getAbsolutePath().replace("\\", "/");
|
||||
conn = DriverManager.getConnection(sqlURL);
|
||||
}
|
||||
|
||||
public static Object getMutex(){
|
||||
return mutex;
|
||||
}
|
||||
|
||||
public static void executeUpdate(String statement){
|
||||
try(PreparedStatement preparedStatement = conn.prepareStatement(statement)){
|
||||
preparedStatement.executeUpdate();
|
||||
}catch(SQLException ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean doesConditionExist(StatementHolder statementHolder){
|
||||
boolean ret = false;
|
||||
|
||||
try(PreparedStatement preparedStatement = statementHolder.getStatement(); ResultSet resultSet = preparedStatement.executeQuery()){
|
||||
ret = resultSet.next();
|
||||
}catch(SQLException ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void executeQuery(String statement, QueryCallback callback){
|
||||
executeQuery(statement, callback, null);
|
||||
}
|
||||
|
||||
public static void executeQuery(String statement, QueryCallback callback, Consumer<SQLException> onFailure){
|
||||
try(PreparedStatement preparedStatement = conn.prepareStatement(statement); ResultSet resultSet = preparedStatement.executeQuery()){
|
||||
callback.run(resultSet);
|
||||
}catch(SQLException ex){
|
||||
if(onFailure == null)
|
||||
ex.printStackTrace();
|
||||
else
|
||||
onFailure.accept(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setAutoCommit(boolean autoCommit){
|
||||
try {
|
||||
conn.setAutoCommit(autoCommit);
|
||||
}catch(SQLException ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void commit(){
|
||||
try {
|
||||
conn.commit();
|
||||
}catch(SQLException ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void close(){
|
||||
try{
|
||||
conn.close();
|
||||
}catch(SQLException ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static PreparedStatement buildStatement(String query) throws SQLException {
|
||||
return conn.prepareStatement(query);
|
||||
}
|
||||
|
||||
public interface QueryCallback{
|
||||
|
||||
void run(ResultSet resultSet) throws SQLException;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,114 +0,0 @@
|
||||
package com.bgsoftware.wildloaders.utils.database;
|
||||
|
||||
import com.bgsoftware.wildloaders.WildLoadersPlugin;
|
||||
import com.bgsoftware.wildloaders.utils.locations.LocationUtils;
|
||||
import com.bgsoftware.wildloaders.utils.threads.Executor;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class StatementHolder {
|
||||
|
||||
private final List<Map<Integer, Object>> batches = new ArrayList<>();
|
||||
private boolean batchStatus = false;
|
||||
|
||||
private final String query;
|
||||
private final Map<Integer, Object> values = new HashMap<>();
|
||||
private int currentIndex = 1;
|
||||
|
||||
StatementHolder(Query query){
|
||||
this.query = query.getStatement();
|
||||
}
|
||||
|
||||
public StatementHolder setString(String value){
|
||||
values.put(currentIndex++, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StatementHolder setInt(int value){
|
||||
values.put(currentIndex++, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StatementHolder setDouble(double value){
|
||||
values.put(currentIndex++, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StatementHolder setLong(long value){
|
||||
values.put(currentIndex++, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StatementHolder setBoolean(boolean value){
|
||||
values.put(currentIndex++, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public StatementHolder setLocation(Location loc){
|
||||
values.put(currentIndex++, loc == null ? "" : LocationUtils.getLocation(loc));
|
||||
return this;
|
||||
}
|
||||
|
||||
public void prepareBatch(){
|
||||
batchStatus = true;
|
||||
}
|
||||
|
||||
public void addBatch(){
|
||||
batches.add(new HashMap<>(values));
|
||||
values.clear();
|
||||
currentIndex = 1;
|
||||
}
|
||||
|
||||
public PreparedStatement getStatement() throws SQLException {
|
||||
PreparedStatement preparedStatement = SQLHelper.buildStatement(query);
|
||||
for(Map.Entry<Integer, Object> entry : values.entrySet()) {
|
||||
preparedStatement.setObject(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return preparedStatement;
|
||||
}
|
||||
|
||||
public void execute(boolean async) {
|
||||
if(async){
|
||||
Executor.data(() -> execute(false));
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (SQLHelper.getMutex()) {
|
||||
String errorQuery = query;
|
||||
try (PreparedStatement preparedStatement = SQLHelper.buildStatement(query)) {
|
||||
if (!batches.isEmpty()) {
|
||||
SQLHelper.setAutoCommit(false);
|
||||
for (Map<Integer, Object> values : batches) {
|
||||
for (Map.Entry<Integer, Object> entry : values.entrySet()) {
|
||||
preparedStatement.setObject(entry.getKey(), entry.getValue());
|
||||
errorQuery = errorQuery.replaceFirst("\\?", entry.getValue() + "");
|
||||
}
|
||||
preparedStatement.addBatch();
|
||||
}
|
||||
preparedStatement.executeBatch();
|
||||
SQLHelper.commit();
|
||||
SQLHelper.setAutoCommit(true);
|
||||
} else if (!batchStatus) {
|
||||
for (Map.Entry<Integer, Object> entry : values.entrySet()) {
|
||||
preparedStatement.setObject(entry.getKey(), entry.getValue());
|
||||
errorQuery = errorQuery.replaceFirst("\\?", entry.getValue() + "");
|
||||
}
|
||||
preparedStatement.executeUpdate();
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
WildLoadersPlugin.log("Failed to execute query " + errorQuery);
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
batchStatus = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user