From 6d20b7bb2a32a1c87d3476cf3af7202fe6bd9f2f Mon Sep 17 00:00:00 2001 From: Lixfel Date: Thu, 16 Sep 2021 21:50:52 +0200 Subject: [PATCH] New SQL API + SchemByUserAndType speedup --- .../src/de/steamwar/core/Core.java | 2 +- SpigotCore_Main/src/de/steamwar/sql/SQL.java | 131 ++++++++++++++---- .../src/de/steamwar/sql/Schematic.java | 14 +- 3 files changed, 112 insertions(+), 35 deletions(-) diff --git a/SpigotCore_Main/src/de/steamwar/core/Core.java b/SpigotCore_Main/src/de/steamwar/core/Core.java index b49d3a5..319d199 100644 --- a/SpigotCore_Main/src/de/steamwar/core/Core.java +++ b/SpigotCore_Main/src/de/steamwar/core/Core.java @@ -71,7 +71,7 @@ public class Core extends JavaPlugin{ @Override public void onDisable(){ - SQL.closeConnection(); + SQL.close(); } public static Core getInstance() { diff --git a/SpigotCore_Main/src/de/steamwar/sql/SQL.java b/SpigotCore_Main/src/de/steamwar/sql/SQL.java index bbe2701..65546cd 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SQL.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SQL.java @@ -24,18 +24,18 @@ import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; import java.sql.*; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; public class SQL { - private SQL(){} - private static final String host; - private static final String port; - private static final String database; - private static final String user; - private static final String password; private static Connection con; + private static String url; + private static String user; + private static String password; static{ File file = new File(Core.getInstance().getDataFolder(), "MySQL.yml"); @@ -44,20 +44,47 @@ public class SQL { if(!file.exists()) throw new SecurityException("SQL-ConfigFile not found!"); - host = config.getString("HOST"); - port = config.getString("PORT"); - database = config.getString("DATABASE"); + url = "jdbc:mysql://" + config.getString("HOST") + ":" + config.getString("PORT") + "/" + config.getString("DATABASE"); user = config.getString("USER"); password = config.getString("PASSWORD"); connect(); } - - public static void closeConnection() { + + private static void connect() { + try { + con = DriverManager.getConnection(url + "?autoreconnect=true", user, password); + } catch (SQLException e) { + throw new SecurityException("Could not start SQL connection", e); + } + } + + public static void close() { + for (Statement statement : Statement.statements) { + try { + statement.st.close(); + } catch (SQLException e) { + Core.getInstance().getLogger().log(Level.INFO, "Could not close statement", e); + } + } + try { con.close(); - }catch (SQLException e) { - throw new SecurityException("Could not close connection", e); + } catch (SQLException e) { + Core.getInstance().getLogger().log(Level.WARNING, "Could not close SQL-Connection", e); + } + } + + private static void reset(SQLException e) { + Core.getInstance().getLogger().log(Level.WARNING, "SQL Exception thrown", e); + close(); + connect(); + try { + for (Statement statement : Statement.statements) { + statement.init(); + } + } catch (SQLException ex) { + throw new SecurityException("Could not reprepare SQL Statements", ex); } } @@ -65,7 +92,7 @@ public class SQL { try { prepare(qry, objects).executeUpdate(); } catch (SQLException e) { - reconnect(); + reset(e); try { prepare(qry, objects).executeUpdate(); } catch (SQLException ex) { @@ -78,7 +105,7 @@ public class SQL { try { return prepare(qry, objects).executeQuery(); } catch (SQLException e) { - reconnect(); + reset(e); try { return prepare(qry, objects).executeQuery(); } catch (SQLException ex) { @@ -91,7 +118,7 @@ public class SQL { try { return con.createBlob(); } catch (SQLException e) { - reconnect(); + reset(e); try { return con.createBlob(); } catch (SQLException ex) { @@ -108,18 +135,66 @@ public class SQL { return st; } - private static void connect() { - try { - con = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database + "?autoreconnect=true", user, password); - if(con.isClosed()) - throw new SQLException("Could not connect to database!"); - }catch (SQLException e) { - throw new SecurityException("No connection to database.", e); + public static class Statement { + private static final List statements = new ArrayList<>(); + + private final String sql; + private PreparedStatement st; + + Statement(String sql) { + this.sql = sql; + statements.add(this); + try { + init(); + } catch (SQLException e) { + reset(e); + } + } + + private synchronized void init() throws SQLException { + st = con.prepareStatement(sql); + } + + T select(ResultSetUser user, Object... objects) { + return prepare(() -> { + ResultSet rs = st.executeQuery(); + T result = user.use(rs); + rs.close(); + return result; + }, objects); + } + + void update(Object... objects) { + prepare(st::executeUpdate, objects); + } + + private synchronized T prepare(SQLRunnable runnable, Object... objects) { + try { + setObjects(objects); + return runnable.run(); + } catch (SQLException e) { + reset(e); + try { + setObjects(objects); + return runnable.run(); + } catch (SQLException ex) { + throw new SecurityException("Could not execute SQL statement", ex); + } + } + } + + private void setObjects(Object... objects) throws SQLException { + for (int i = 0; i < objects.length; i++) { + st.setObject(i + 1, objects[i]); + } + } + + interface ResultSetUser { + T use(ResultSet rs) throws SQLException; + } + + private interface SQLRunnable { + T run() throws SQLException; } } - - private static void reconnect(){ - closeConnection(); - connect(); - } } diff --git a/SpigotCore_Main/src/de/steamwar/sql/Schematic.java b/SpigotCore_Main/src/de/steamwar/sql/Schematic.java index c08bcec..dbbd123 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/Schematic.java +++ b/SpigotCore_Main/src/de/steamwar/sql/Schematic.java @@ -35,6 +35,8 @@ import java.util.zip.GZIPInputStream; public class Schematic { + private static final SQL.Statement getSchemsOfType = new SQL.Statement("SELECT DISTINCT s.SchemID, s.SchemName, s.SchemOwner, s.Item, s.SchemType, s.Rank, s.SchemFormat FROM Schematic s LEFT JOIN SchemMember sm ON sm.SchemName = s.SchemName AND sm.SchemOwner = s.SchemOwner WHERE s.SchemType = ? AND (s.SchemOwner = ? OR sm.Member = ?) ORDER BY s.SchemName"); + private final int schemID; private final String schemName; private final int schemOwner; @@ -118,12 +120,12 @@ public class Schematic { } public static List getSchemsOfType(int schemOwner, SchematicType schemType){ - //Unsauber, dafür auch geaddede Schematics dabei - List schems = getSchemsAccessibleByUser(schemOwner); - for(int i = schems.size()-1; i >= 0; i--) - if(!schems.get(i).getSchemType().equals(schemType)) - schems.remove(i); - return schems; + return getSchemsOfType.select(rs -> { + List schematics = new ArrayList<>(); + while(rs.next()) + schematics.add(new Schematic(rs)); + return schematics; + }, schemType.toDB(), schemOwner, schemOwner); } public static List getAllSchemsOfType(SchematicType schemType){