diff --git a/pom.xml b/pom.xml
index e338e7c..7c6c57b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -140,6 +140,16 @@
2.4.0
provided
+
+ com.zaxxer
+ HikariCP
+ 3.2.0
+
+
+ org.slf4j
+ slf4j-jdk14
+ 1.7.25
+
diff --git a/src/main/java/de/epiceric/shopchest/exceptions/WorldNotFoundException.java b/src/main/java/de/epiceric/shopchest/exceptions/WorldNotFoundException.java
index 57ec094..4578846 100644
--- a/src/main/java/de/epiceric/shopchest/exceptions/WorldNotFoundException.java
+++ b/src/main/java/de/epiceric/shopchest/exceptions/WorldNotFoundException.java
@@ -2,8 +2,8 @@ package de.epiceric.shopchest.exceptions;
public class WorldNotFoundException extends Exception {
- public WorldNotFoundException(String message) {
- super(message);
+ public WorldNotFoundException(String worldName) {
+ super("Could not find world with name \"" + worldName + "\"");
}
}
diff --git a/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java b/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java
index ca4d4be..f9eda64 100644
--- a/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java
+++ b/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java
@@ -1028,7 +1028,7 @@ public class ShopInteractListener implements Listener {
return;
}
- database.logEconomy(executor, newProduct, shop.getVendor(), shop.getShopType(), shop.getLocation(), newPrice, ShopBuySellEvent.Type.BUY, null);
+ database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.BUY, null);
addToInventory(inventory, newProduct);
removeFromInventory(c.getInventory(), newProduct);
@@ -1072,7 +1072,7 @@ public class ShopInteractListener implements Listener {
return;
}
- database.logEconomy(executor, newProduct, shop.getVendor(), shop.getShopType(), shop.getLocation(), newPrice, ShopBuySellEvent.Type.BUY, null);
+ database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.BUY, null);
addToInventory(inventory, newProduct);
executor.updateInventory();
@@ -1192,7 +1192,7 @@ public class ShopInteractListener implements Listener {
return;
}
- database.logEconomy(executor, newProduct, shop.getVendor(), shop.getShopType(), shop.getLocation(), newPrice, ShopBuySellEvent.Type.SELL, null);
+ database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.SELL, null);
addToInventory(inventory, newProduct);
removeFromInventory(executor.getInventory(), newProduct);
@@ -1237,7 +1237,7 @@ public class ShopInteractListener implements Listener {
return;
}
- database.logEconomy(executor, newProduct, shop.getVendor(), shop.getShopType(), shop.getLocation(), newPrice, ShopBuySellEvent.Type.SELL, null);
+ database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.SELL, null);
removeFromInventory(executor.getInventory(), newProduct);
executor.updateInventory();
diff --git a/src/main/java/de/epiceric/shopchest/sql/Database.java b/src/main/java/de/epiceric/shopchest/sql/Database.java
index 1248f45..466813c 100644
--- a/src/main/java/de/epiceric/shopchest/sql/Database.java
+++ b/src/main/java/de/epiceric/shopchest/sql/Database.java
@@ -3,6 +3,7 @@ package de.epiceric.shopchest.sql;
import de.epiceric.shopchest.ShopChest;
import de.epiceric.shopchest.config.Config;
import de.epiceric.shopchest.event.ShopBuySellEvent;
+import de.epiceric.shopchest.event.ShopBuySellEvent.Type;
import de.epiceric.shopchest.exceptions.WorldNotFoundException;
import de.epiceric.shopchest.language.LanguageUtils;
import de.epiceric.shopchest.shop.Shop;
@@ -28,86 +29,83 @@ import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
+import com.zaxxer.hikari.HikariDataSource;
+
public abstract class Database {
private static Set notFoundWorlds = new HashSet<>();
ShopChest plugin;
- Connection connection;
+ HikariDataSource dataSource;
- Database(ShopChest plugin) {
+ protected Database(ShopChest plugin) {
this.plugin = plugin;
}
- /**
- * @return New connection to the database
- */
- public abstract Connection getConnection();
+ abstract HikariDataSource getDataSource();
/**
* (Re-)Connects to the the database and initializes it.
* Creates the table (if doesn't exist) and tests the connection
- * @param callback Callback that - if succeeded - returns the amount of shops that were found (as {@code int})
+ *
+ * @param callback Callback that - if succeeded - returns the amount of shops
+ * that were found (as {@code int})
*/
public void connect(final Callback callback) {
new BukkitRunnable() {
@Override
public void run() {
+ disconnect();
+
+ dataSource = getDataSource();
+
+ String queryCreateTableShopList =
+ "CREATE TABLE IF NOT EXISTS shops ("
+ + "id INTEGER PRIMARY KEY " + (Database.this instanceof SQLite ? "AUTOINCREMENT" : "AUTO_INCREMENT") + ","
+ + "vendor TINYTEXT NOT NULL,"
+ + "product TEXT NOT NULL,"
+ + "world TINYTEXT NOT NULL,"
+ + "x INTEGER NOT NULL,"
+ + "y INTEGER NOT NULL,"
+ + "z INTEGER NOT NULL,"
+ + "buyprice FLOAT NOT NULL,"
+ + "sellprice FLOAT NOT NULL,"
+ + "shoptype TINYTEXT NOT NULL)";
+
+ String queryCreateTableShopLog =
+ "CREATE TABLE IF NOT EXISTS `shop_log` ("
+ + "id INTEGER PRIMARY KEY " + (Database.this instanceof SQLite ? "AUTOINCREMENT" : "AUTO_INCREMENT") + ","
+ + "timestamp TINYTEXT NOT NULL,"
+ + "executor TINYTEXT NOT NULL,"
+ + "product TINYTEXT NOT NULL,"
+ + "vendor TINYTEXT NOT NULL,"
+ + "world TINYTEXT NOT NULL,"
+ + "x INTEGER NOT NULL,"
+ + "y INTEGER NOT NULL,"
+ + "z INTEGER NOT NULL,"
+ + "price FLOAT NOT NULL,"
+ + "type TINYTEXT NOT NULL)";
+
+ String queryCreateTablePlayerLogout =
+ "CREATE TABLE IF NOT EXISTS player_logout ("
+ + "player VARCHAR(36) PRIMARY KEY NOT NULL,"
+ + "time LONG NOT NULL)";
+
try {
- disconnect();
-
- plugin.debug("Connecting to database...");
- connection = getConnection();
-
- String queryCreateTableShopList =
- "CREATE TABLE IF NOT EXISTS shops (" +
- "id INTEGER PRIMARY KEY " + (Database.this instanceof SQLite ? "AUTOINCREMENT" : "AUTO_INCREMENT") + "," +
- "vendor TINYTEXT NOT NULL," +
- "product TEXT NOT NULL," +
- "world TINYTEXT NOT NULL," +
- "x INTEGER NOT NULL," +
- "y INTEGER NOT NULL," +
- "z INTEGER NOT NULL," +
- "buyprice FLOAT NOT NULL," +
- "sellprice FLOAT NOT NULL," +
- "shoptype TINYTEXT NOT NULL" +
- ")";
-
- String queryCreateTableShopLog =
- "CREATE TABLE IF NOT EXISTS `shop_log` (" +
- "id INTEGER PRIMARY KEY " + (Database.this instanceof SQLite ? "AUTOINCREMENT" : "AUTO_INCREMENT") + "," +
- "timestamp TINYTEXT NOT NULL," +
- "executor TINYTEXT NOT NULL," +
- "product TINYTEXT NOT NULL," +
- "vendor TINYTEXT NOT NULL," +
- "world TINYTEXT NOT NULL," +
- "x INTEGER NOT NULL," +
- "y INTEGER NOT NULL," +
- "z INTEGER NOT NULL," +
- "price FLOAT NOT NULL," +
- "type TINYTEXT NOT NULL" +
- ")";
-
- String queryCreateTablePlayerLogout =
- "CREATE TABLE IF NOT EXISTS player_logout (" +
- "player VARCHAR(36) PRIMARY KEY NOT NULL," +
- "time LONG NOT NULL" +
- ")";
-
// Create table "shops"
- Statement s = connection.createStatement();
- s.executeUpdate(queryCreateTableShopList);
- s.close();
+ try (Connection con = dataSource.getConnection(); Statement s = con.createStatement()) {
+ s.executeUpdate(queryCreateTableShopList);
+ }
// Create table "shop_log"
- Statement s2 = connection.createStatement();
- s2.executeUpdate(queryCreateTableShopLog);
- s2.close();
+ try (Connection con = dataSource.getConnection(); Statement s = con.createStatement()) {
+ s.executeUpdate(queryCreateTableShopLog);
+ }
// Create table "player_logout"
- Statement s3 = connection.createStatement();
- s3.executeUpdate(queryCreateTablePlayerLogout);
- s3.close();
+ try (Connection con = dataSource.getConnection(); Statement s = con.createStatement()) {
+ s.executeUpdate(queryCreateTablePlayerLogout);
+ }
// Clean up economy log
if (Config.cleanupEconomyLogDays > 0) {
@@ -115,23 +113,28 @@ public abstract class Database {
}
// Count entries in table "shops"
- PreparedStatement ps = connection.prepareStatement("SELECT * FROM shops");
- ResultSet rs2 = ps.executeQuery();
+ try (Connection con = dataSource.getConnection(); Statement s = con.createStatement();) {
+ ResultSet rs = s.executeQuery("SELECT id FROM shops");
- int count = 0;
- while (rs2.next()) {
- if (rs2.getString("vendor") != null) count++;
+ int count = 0;
+ while (rs.next()) {
+ count++;
+ }
+
+ plugin.debug("Initialized database with " + count + " entries");
+
+ if (callback != null) {
+ callback.callSyncResult(count);
+ }
}
- plugin.debug("Initialized database with " + count + " entries");
-
- close(ps, rs2);
-
- if (callback != null) callback.callSyncResult(count);
- } catch (SQLException ex) {
- if (callback != null) callback.callSyncError(ex);
+ } catch (SQLException e) {
+ if (callback != null) {
+ callback.callSyncError(e);
+ }
+
plugin.getLogger().severe("Failed to initialize database");
plugin.debug("Failed to initialize database");
- plugin.debug(ex);
+ plugin.debug(e);
}
}
}.runTaskAsynchronously(plugin);
@@ -140,65 +143,70 @@ public abstract class Database {
/**
* Remove a shop from the database
*
- * @param shop Shop to remove
+ * @param shop Shop to remove
* @param callback Callback that - if succeeded - returns {@code null}
*/
public void removeShop(final Shop shop, final Callback callback) {
new BukkitRunnable() {
@Override
public void run() {
- PreparedStatement ps = null;
-
- try {
- ps = connection.prepareStatement("DELETE FROM shops WHERE id = ?");
+ try (Connection con = dataSource.getConnection();
+ PreparedStatement ps = con.prepareStatement("DELETE FROM shops WHERE id = ?")) {
ps.setInt(1, shop.getID());
ps.executeUpdate();
plugin.debug("Removing shop from database (#" + shop.getID() + ")");
- if (callback != null) callback.callSyncResult(null);
+
+ if (callback != null) {
+ callback.callSyncResult(null);
+ }
} catch (SQLException ex) {
- if (callback != null) callback.callSyncError(ex);
+ if (callback != null) {
+ callback.callSyncError(ex);
+ }
+
plugin.getLogger().severe("Failed to access database");
plugin.debug("Failed to remove shop from database (#" + shop.getID() + ")");
plugin.debug(ex);
- } finally {
- close(ps, null);
}
}
}.runTaskAsynchronously(plugin);
}
/**
- * @param id ID of the shop
- * @param callback Callback that - if succeeded - returns whether a shop with the given ID exists (as {@code boolean})
+ * @param id ID of the shop
+ * @param callback Callback that - if succeeded - returns whether a shop with
+ * the given ID exists (as {@code boolean})
*/
public void isShop(final int id, final Callback callback) {
new BukkitRunnable() {
@Override
public void run() {
- PreparedStatement ps = null;
- ResultSet rs = null;
-
- try {
- ps = connection.prepareStatement("SELECT * FROM shops WHERE id = ?");
+ try (Connection con = dataSource.getConnection();
+ PreparedStatement ps = con.prepareStatement("SELECT * FROM shops WHERE id = ?")) {
ps.setInt(1, id);
- rs = ps.executeQuery();
+ ResultSet rs = ps.executeQuery();
while (rs.next()) {
if (rs.getInt("id") == id) {
- if (callback != null) callback.callSyncResult(true);
+ if (callback != null) {
+ callback.callSyncResult(true);
+ }
return;
}
}
- if (callback != null) callback.callSyncResult(false);
+ if (callback != null) {
+ callback.callSyncResult(false);
+ }
} catch (SQLException ex) {
- if (callback != null) callback.callSyncError(ex);
+ if (callback != null) {
+ callback.callSyncError(ex);
+ }
+
plugin.getLogger().severe("Failed to access database");
plugin.debug("Failed to check if shop with ID exists (#" + id + ")");
plugin.debug(ex);
- } finally {
- close(ps, rs);
}
}
}.runTaskAsynchronously(plugin);
@@ -206,21 +214,22 @@ public abstract class Database {
/**
* Get all shops from the database
- * @param callback Callback that - if succeeded - returns a read-only collection of all shops (as {@code Collection})
- * @param showConsoleMessages Whether console messages (errors or warnings) should be shown
+ *
+ * @param callback Callback that - if succeeded - returns a read-only
+ * collection of all shops (as
+ * {@code Collection})
+ * @param showConsoleMessages Whether console messages (errors or warnings)
+ * should be shown
*/
public void getShops(final boolean showConsoleMessages, final Callback> callback) {
new BukkitRunnable() {
@Override
public void run() {
- PreparedStatement ps = null;
- ResultSet rs = null;
-
ArrayList shops = new ArrayList<>();
- try {
- ps = connection.prepareStatement("SELECT * FROM shops");
- rs = ps.executeQuery();
+ try (Connection con = dataSource.getConnection();
+ PreparedStatement ps = con.prepareStatement("SELECT * FROM shops")) {
+ ResultSet rs = ps.executeQuery();
while (rs.next()) {
int id = rs.getInt("id");
@@ -234,9 +243,11 @@ public abstract class Database {
int z = rs.getInt("z");
if (world == null) {
- WorldNotFoundException ex = new WorldNotFoundException("Could not find world with name \"" + worldName + "\"");
- if (showConsoleMessages && !notFoundWorlds.contains(worldName)) plugin.getLogger().warning(ex.getMessage());
- notFoundWorlds.add(worldName);
+ WorldNotFoundException ex = new WorldNotFoundException(worldName);
+ if (showConsoleMessages && !notFoundWorlds.contains(worldName)) {
+ plugin.getLogger().warning(ex.getMessage());
+ notFoundWorlds.add(worldName);
+ }
plugin.debug("Failed to get shop (#" + id + ")");
plugin.debug(ex);
continue;
@@ -255,80 +266,81 @@ public abstract class Database {
shops.add(new Shop(id, plugin, vendor, product, location, buyPrice, sellPrice, shopType));
}
- if (callback != null) callback.callSyncResult(Collections.unmodifiableCollection(shops));
+ if (callback != null) {
+ callback.callSyncResult(Collections.unmodifiableCollection(shops));
+ }
} catch (SQLException ex) {
- if (callback != null) callback.callSyncError(ex);
+ if (callback != null) {
+ callback.callSyncError(ex);
+ }
+
plugin.getLogger().severe("Failed to access database");
plugin.debug("Failed to get shops");
plugin.debug(ex);
- } finally {
- close(ps, rs);
}
-
}
}.runTaskAsynchronously(plugin);
}
/**
* Adds a shop to the database
- * @param shop Shop to add
- * @param callback Callback that - if succeeded - returns the ID the shop was given (as {@code int})
+ *
+ * @param shop Shop to add
+ * @param callback Callback that - if succeeded - returns the ID the shop was
+ * given (as {@code int})
*/
public void addShop(final Shop shop, final Callback callback) {
+ final String queryNoId = "REPLACE INTO shops (vendor,product,world,x,y,z,buyprice,sellprice,shoptype) VALUES(?,?,?,?,?,?,?,?,?)";
+ final String queryWithId = "REPLACE INTO shops (id,vendor,product,world,x,y,z,buyprice,sellprice,shoptype) VALUES(?,?,?,?,?,?,?,?,?,?)";
+
new BukkitRunnable() {
@Override
public void run() {
- PreparedStatement ps = null;
- ResultSet rs = null;
+ String query = shop.hasId() ? queryWithId : queryNoId;
+
+ try (Connection con = dataSource.getConnection();
+ PreparedStatement ps = con.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) {
+ int i = 0;
+ if (shop.hasId()) {
+ i = 1;
+ ps.setInt(1, shop.getID());
+ }
+
+ ps.setString(i+1, shop.getVendor().getUniqueId().toString());
+ ps.setString(i+2, Utils.encode(shop.getProduct()));
+ ps.setString(i+3, shop.getLocation().getWorld().getName());
+ ps.setInt(i+4, shop.getLocation().getBlockX());
+ ps.setInt(i+5, shop.getLocation().getBlockY());
+ ps.setInt(i+6, shop.getLocation().getBlockZ());
+ ps.setDouble(i+7, shop.getBuyPrice());
+ ps.setDouble(i+8, shop.getSellPrice());
+ ps.setString(i+9, shop.getShopType().toString());
+ ps.executeUpdate();
- try {
if (!shop.hasId()) {
- ps = connection.prepareStatement("REPLACE INTO shops (vendor,product,world,x,y,z,buyprice,sellprice,shoptype) VALUES(?,?,?,?,?,?,?,?,?)", Statement.RETURN_GENERATED_KEYS);
-
- ps.setString(1, shop.getVendor().getUniqueId().toString());
- ps.setString(2, Utils.encode(shop.getProduct()));
- ps.setString(3, shop.getLocation().getWorld().getName());
- ps.setInt(4, shop.getLocation().getBlockX());
- ps.setInt(5, shop.getLocation().getBlockY());
- ps.setInt(6, shop.getLocation().getBlockZ());
- ps.setDouble(7, shop.getBuyPrice());
- ps.setDouble(8, shop.getSellPrice());
- ps.setString(9, shop.getShopType().toString());
- ps.executeUpdate();
-
int shopId = -1;
- rs = ps.getGeneratedKeys();
+ ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) {
shopId = rs.getInt(1);
}
shop.setId(shopId);
- } else {
- ps = connection.prepareStatement("REPLACE INTO shops (id,vendor,product,world,x,y,z,buyprice,sellprice,shoptype) VALUES(?,?,?,?,?,?,?,?,?,?)");
-
- ps.setInt(1, shop.getID());
- ps.setString(2, shop.getVendor().getUniqueId().toString());
- ps.setString(3, Utils.encode(shop.getProduct()));
- ps.setString(4, shop.getLocation().getWorld().getName());
- ps.setInt(5, shop.getLocation().getBlockX());
- ps.setInt(6, shop.getLocation().getBlockY());
- ps.setInt(7, shop.getLocation().getBlockZ());
- ps.setDouble(8, shop.getBuyPrice());
- ps.setDouble(9, shop.getSellPrice());
- ps.setString(10, shop.getShopType().toString());
- ps.executeUpdate();
}
- if (callback != null) callback.callSyncResult(shop.getID());
+ if (callback != null) {
+ callback.callSyncResult(shop.getID());
+ }
+
plugin.debug("Adding shop to database (#" + shop.getID() + ")");
} catch (SQLException ex) {
- if (callback != null) callback.callSyncError(ex);
+ if (callback != null) {
+ callback.callSyncError(ex);
+ }
+
plugin.getLogger().severe("Failed to access database");
plugin.debug("Failed to add shop to database (#" + shop.getID() + ")");
plugin.debug(ex);
- } finally {
- close(ps, rs);
}
}
}.runTaskAsynchronously(plugin);
@@ -336,65 +348,67 @@ public abstract class Database {
/**
* Log an economy transaction to the database
+ *
* @param executor Player who bought/sold something
- * @param product {@link ItemStack} that was bought/sold
- * @param vendor Vendor of the shop
- * @param shopType {@link ShopType} of the shop
- * @param location Location of the shop
- * @param price Price (buyprice or sellprice, depends on {@code type})
- * @param type Whether the player bought or sold something
+ * @param shop The {@link Shop} the player bought from or sold to
+ * @param product The {@link ItemStack} that was bought/sold
+ * @param price The price the product was bought or sold for
+ * @param type Whether the executor bought or sold
* @param callback Callback that - if succeeded - returns {@code null}
*/
- public void logEconomy(final Player executor, final ItemStack product, final OfflinePlayer vendor, final ShopType shopType, final Location location, final double price, final ShopBuySellEvent.Type type, final Callback callback) {
+ public void logEconomy(final Player executor, Shop shop, ItemStack product, double price, Type type, final Callback callback) {
+ final String query = "INSERT INTO shop_log (timestamp,executor,product,vendor,world,x,y,z,price,type) VALUES(?,?,?,?,?,?,?,?,?,?)";
if (Config.enableEconomyLog) {
new BukkitRunnable() {
@Override
public void run() {
- PreparedStatement ps = null;
-
- try {
- ps = connection.prepareStatement("INSERT INTO shop_log (timestamp,executor,product,vendor,world,x,y,z,price,type) VALUES(?,?,?,?,?,?,?,?,?,?)");
+ try (Connection con = dataSource.getConnection();
+ PreparedStatement ps = con.prepareStatement(query)) {
ps.setString(1, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime()));
ps.setString(2, executor.getUniqueId().toString() + " (" + executor.getName() + ")");
ps.setString(3, product.getAmount() + " x " + LanguageUtils.getItemName(product));
- ps.setString(4, vendor.getUniqueId().toString() + " (" + vendor.getName() + ")" + (shopType == ShopType.ADMIN ? " (ADMIN)" : ""));
- ps.setString(5, location.getWorld().getName());
- ps.setInt(6, location.getBlockX());
- ps.setInt(7, location.getBlockY());
- ps.setInt(8, location.getBlockZ());
+ ps.setString(4, shop.getVendor().getUniqueId().toString() + " (" + shop.getVendor().getName() + ")" + (shop.getShopType() == ShopType.ADMIN ? " (ADMIN)" : ""));
+ ps.setString(5, shop.getLocation().getWorld().getName());
+ ps.setInt(6, shop.getLocation().getBlockX());
+ ps.setInt(7, shop.getLocation().getBlockY());
+ ps.setInt(8, shop.getLocation().getBlockZ());
ps.setDouble(9, price);
ps.setString(10, type.toString());
ps.executeUpdate();
- if (callback != null) callback.callSyncResult(null);
+ if (callback != null) {
+ callback.callSyncResult(null);
+ }
+
plugin.debug("Logged economy transaction to database");
- } catch (final SQLException ex) {
- if (callback != null) callback.callSyncError(ex);
+ } catch (SQLException ex) {
+ if (callback != null) {
+ callback.callSyncError(ex);
+ }
+
plugin.getLogger().severe("Failed to access database");
plugin.debug("Failed to log economy transaction to database");
plugin.debug(ex);
- } finally {
- close(ps, null);
}
}
}.runTaskAsynchronously(plugin);
} else {
- if (callback != null) callback.callSyncResult(null);
+ if (callback != null) {
+ callback.callSyncResult(null);
+ }
}
}
/**
* Cleans up the economy log to reduce file size
+ *
* @param async Whether the call should be executed asynchronously
*/
public void cleanUpEconomy(boolean async) {
BukkitRunnable runnable = new BukkitRunnable() {
@Override
public void run() {
- Statement s = null;
- Statement s2 = null;
-
Calendar cal = Calendar.getInstance();
long time = System.currentTimeMillis();
cal.add(Calendar.DATE, -Config.cleanupEconomyLogDays);
@@ -403,22 +417,18 @@ public abstract class Database {
String queryCleanUpLog = "DELETE FROM shop_log WHERE timestamp < '" + logPurgeLimit + "'";
String queryCleanUpPlayers = "DELETE FROM player_logout WHERE time < " + String.valueOf(time);
- try {
- s = connection.createStatement();
+ try (Connection con = dataSource.getConnection();
+ Statement s = con.createStatement();
+ Statement s2 = con.createStatement()) {
s.executeUpdate(queryCleanUpLog);
-
- s2 = connection.createStatement();
s2.executeUpdate(queryCleanUpPlayers);
plugin.getLogger().info("Cleaned up economy log");
plugin.debug("Cleaned up economy log");
- } catch (final SQLException ex) {
+ } catch (SQLException ex) {
plugin.getLogger().severe("Failed to clean up economy log");
plugin.debug("Failed to clean up economy log");
plugin.debug(ex);
- } finally {
- close(s, null);
- close(s2, null);
}
}
};
@@ -432,32 +442,32 @@ public abstract class Database {
/**
* Get the revenue a player got while he was offline
- * @param player Player whose revenue to get
+ *
+ * @param player Player whose revenue to get
* @param logoutTime Time in milliseconds when he logged out the last time
- * @param callback Callback that - if succeeded - returns the revenue the player made while offline (as {@code double})
+ * @param callback Callback that - if succeeded - returns the revenue the
+ * player made while offline (as {@code double})
*/
public void getRevenue(final Player player, final long logoutTime, final Callback callback) {
new BukkitRunnable() {
@Override
public void run() {
- PreparedStatement ps = null;
- ResultSet rs = null;
-
String vendor = String.format("%s (%s)", player.getUniqueId().toString(), player.getName());
-
double revenue = 0;
- try {
- ps = connection.prepareStatement("SELECT * FROM shop_log WHERE vendor = ?;");
+ try (Connection con = dataSource.getConnection();
+ PreparedStatement ps = con.prepareStatement("SELECT * FROM shop_log WHERE vendor = ?")) {
ps.setString(1, vendor);
- rs = ps.executeQuery();
+ ResultSet rs = ps.executeQuery();
while (rs.next()) {
if (rs.getString("vendor").equals(vendor)) {
double singleRevenue = rs.getDouble("price");
ShopBuySellEvent.Type type = ShopBuySellEvent.Type.valueOf(rs.getString("type"));
- if (type == ShopBuySellEvent.Type.SELL) singleRevenue = -singleRevenue;
+ if (type == ShopBuySellEvent.Type.SELL) {
+ singleRevenue = -singleRevenue;
+ }
long timestamp;
@@ -475,14 +485,17 @@ public abstract class Database {
}
}
- if (callback != null) callback.callSyncResult(revenue);
+ if (callback != null) {
+ callback.callSyncResult(revenue);
+ }
} catch (SQLException ex) {
- if (callback != null) callback.callSyncError(ex);
+ if (callback != null) {
+ callback.callSyncError(ex);
+ }
+
plugin.getLogger().severe("Failed to access database");
plugin.debug("Failed to get revenue from player \"" + player.getUniqueId().toString() + "\"");
plugin.debug(ex);
- } finally {
- close(ps, rs);
}
}
}.runTaskAsynchronously(plugin);
@@ -490,32 +503,35 @@ public abstract class Database {
/**
* Log a logout to the database
- * @param player Player who logged out
+ *
+ * @param player Player who logged out
* @param timestamp Time in milliseconds when the player logged out
- * @param callback Callback that - if succeeded - returns {@code null}
+ * @param callback Callback that - if succeeded - returns {@code null}
*/
public void logLogout(final Player player, final long timestamp, final Callback callback) {
new BukkitRunnable() {
@Override
public void run() {
- PreparedStatement ps = null;
-
- try {
- ps = connection.prepareStatement("REPLACE INTO player_logout (player,time) VALUES(?,?)");
+ try (Connection con = dataSource.getConnection();
+ PreparedStatement ps = con.prepareStatement("REPLACE INTO player_logout (player,time) VALUES(?,?)")) {
ps.setString(1, player.getUniqueId().toString());
ps.setLong(2, timestamp);
ps.executeUpdate();
- if (callback != null) callback.callSyncResult(null);
+ if (callback != null) {
+ callback.callSyncResult(null);
+ }
+
plugin.debug("Logged logout to database");
} catch (final SQLException ex) {
- if (callback != null) callback.callSyncError(ex);
+ if (callback != null) {
+ callback.callSyncError(ex);
+ }
+
plugin.getLogger().severe("Failed to access database");
plugin.debug("Failed to log logout to database");
plugin.debug(ex);
- } finally {
- close(ps, null);
}
}
}.runTaskAsynchronously(plugin);
@@ -523,78 +539,57 @@ public abstract class Database {
/**
* Get the last logout of a player
- * @param player Player who logged out
- * @param callback Callback that - if succeeded - returns the time in milliseconds the player logged out (as {@code long})
+ *
+ * @param player Player who logged out
+ * @param callback Callback that - if succeeded - returns the time in
+ * milliseconds the player logged out (as {@code long})
*/
public void getLastLogout(final Player player, final Callback callback) {
new BukkitRunnable() {
@Override
public void run() {
- PreparedStatement ps = null;
- ResultSet rs = null;
+ String uuid = player.getUniqueId().toString();
- String playerUuid = player.getUniqueId().toString();
-
- try {
- ps = connection.prepareStatement("SELECT * FROM player_logout WHERE player=?;");
- ps.setString(1, playerUuid);
- rs = ps.executeQuery();
+ try (Connection con = dataSource.getConnection();
+ PreparedStatement ps = con.prepareStatement("SELECT * FROM player_logout WHERE player = ?")) {
+ ps.setString(1, uuid);
+ ResultSet rs = ps.executeQuery();
while (rs.next()) {
- if (rs.getString("player").equals(playerUuid)) {
- if (callback != null) callback.callSyncResult(rs.getLong("time"));
+ if (rs.getString("player").equals(uuid)) {
+ if (callback != null) {
+ callback.callSyncResult(rs.getLong("time"));
+ }
return;
}
}
- if (callback != null) callback.callSyncResult(-1L);
+ if (callback != null) {
+ callback.callSyncResult(-1L);
+ }
} catch (SQLException ex) {
- if (callback != null) callback.callSyncError(ex);
+ if (callback != null) {
+ callback.callSyncError(ex);
+ }
+
plugin.getLogger().severe("Failed to access database");
- plugin.debug("Failed to get last logout from player \"" + playerUuid + "\"");
+ plugin.debug("Failed to get last logout from player \"" + player.getName() + "\"");
plugin.debug(ex);
- } finally {
- close(ps, rs);
}
}
}.runTaskAsynchronously(plugin);
}
/**
- * Closes a {@link Statement} and a {@link ResultSet}
- * @param s {@link Statement} to close
- * @param rs {@link ResultSet} to close
- */
- void close(Statement s, ResultSet rs) {
- try {
- if (s != null)
- s.close();
- if (rs != null)
- rs.close();
- } catch (SQLException ex) {
- plugin.debug("Failed to close PreparedStatement/ResultSet");
- plugin.debug(ex);
- }
- }
-
- /**
- * Closes the connection to the database
+ * Closes the data source
*/
public void disconnect() {
- try {
- if (connection != null && !connection.isClosed()) {
- plugin.debug("Disconnecting from database...");
- connection.close();
- }
- } catch (SQLException e) {
- plugin.getLogger().severe("Failed to disconnect from database");
- plugin.debug("Failed to disconnect from database");
- plugin.debug(e);
+ if (dataSource != null) {
+ dataSource.close();
}
}
public enum DatabaseType {
- SQLite,
- MySQL
+ SQLite, MySQL
}
}
\ No newline at end of file
diff --git a/src/main/java/de/epiceric/shopchest/sql/MySQL.java b/src/main/java/de/epiceric/shopchest/sql/MySQL.java
index baf293c..4997eba 100644
--- a/src/main/java/de/epiceric/shopchest/sql/MySQL.java
+++ b/src/main/java/de/epiceric/shopchest/sql/MySQL.java
@@ -5,9 +5,11 @@ import de.epiceric.shopchest.config.Config;
import org.bukkit.scheduler.BukkitRunnable;
import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
import java.sql.SQLException;
+import java.sql.Statement;
+
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
public class MySQL extends Database {
@@ -16,36 +18,27 @@ public class MySQL extends Database {
}
@Override
- public Connection getConnection() {
- try {
- if (connection != null && !connection.isClosed()) {
- return connection;
- }
+ HikariDataSource getDataSource() {
+ HikariConfig config = new HikariConfig();
+ config.setJdbcUrl(String.format("jdbc:mysql://%s:%d/%s?autoReconnect=true&useSSL=false",
+ Config.databaseMySqlHost, Config.databaseMySqlPort, Config.databaseMySqlDatabase));
+ config.setUsername(Config.databaseMySqlUsername);
+ config.setPassword(Config.databaseMySqlPassword);
- Class.forName("com.mysql.jdbc.Driver");
-
- String connectUrl = "jdbc:mysql://" + Config.databaseMySqlHost + ":" + Config.databaseMySqlPort + "/" + Config.databaseMySqlDatabase + "?autoReconnect=true&useSSL=false";
- plugin.debug("Connecting to MySQL Server \"" + connectUrl + "\" as user \"" + Config.databaseMySqlUsername + "\"");
-
- connection = DriverManager.getConnection(connectUrl, Config.databaseMySqlUsername, Config.databaseMySqlPassword);
-
- return connection;
- } catch (Exception ex) {
- plugin.getLogger().severe("Failed to get database connection");
- plugin.debug("Failed to get database connection");
- plugin.debug(ex);
- }
-
- return null;
+ return new HikariDataSource(config);
}
+ /**
+ * Sends an asynchronous ping to the database
+ */
public void ping() {
new BukkitRunnable() {
@Override
public void run() {
- try (PreparedStatement ps = connection.prepareStatement("/* ping */ SELECT 1")) {
+ try (Connection con = dataSource.getConnection();
+ Statement s = con.createStatement()) {
plugin.debug("Pinging to MySQL server...");
- ps.executeQuery();
+ s.execute("/* ping */ SELECT 1");
} catch (SQLException ex) {
plugin.getLogger().severe("Failed to ping to MySQL server. Trying to reconnect...");
plugin.debug("Failed to ping to MySQL server. Trying to reconnect...");
diff --git a/src/main/java/de/epiceric/shopchest/sql/SQLite.java b/src/main/java/de/epiceric/shopchest/sql/SQLite.java
index 8175854..d289f99 100644
--- a/src/main/java/de/epiceric/shopchest/sql/SQLite.java
+++ b/src/main/java/de/epiceric/shopchest/sql/SQLite.java
@@ -6,10 +6,12 @@ import org.bukkit.scheduler.BukkitRunnable;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
-import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+
public class SQLite extends Database {
public SQLite(ShopChest plugin) {
@@ -17,7 +19,7 @@ public class SQLite extends Database {
}
@Override
- public Connection getConnection() {
+ HikariDataSource getDataSource() {
File folder = plugin.getDataFolder();
File dbFile = new File(folder, "shops.db");
@@ -30,37 +32,24 @@ public class SQLite extends Database {
plugin.debug(ex);
}
}
+
+ HikariConfig config = new HikariConfig();
+ config.setJdbcUrl(String.format("jdbc:sqlite:" + dbFile));
- try {
- if (connection != null && !connection.isClosed()) {
- return connection;
- }
-
- Class.forName("org.sqlite.JDBC");
- connection = DriverManager.getConnection("jdbc:sqlite:" + dbFile);
-
- return connection;
- } catch (ClassNotFoundException | SQLException ex) {
- plugin.getLogger().severe("Failed to get database connection");
- plugin.debug("Failed to get database connection");
- plugin.debug(ex);
- }
-
- return null;
+ return new HikariDataSource(config);
}
/**
* Vacuums the database to reduce file size
+ *
* @param async Whether the call should be executed asynchronously
*/
public void vacuum(boolean async) {
BukkitRunnable runnable = new BukkitRunnable() {
@Override
public void run() {
- Statement s = null;
-
- try {
- s = connection.createStatement();
+ try (Connection con = dataSource.getConnection();
+ Statement s = con.createStatement()) {
s.executeUpdate("VACUUM");
plugin.debug("Vacuumed SQLite database");
@@ -68,8 +57,6 @@ public class SQLite extends Database {
plugin.getLogger().severe("Failed to access database");
plugin.debug("Failed to vacuum database");
plugin.debug(ex);
- } finally {
- close(s, null);
}
}
};