Merge pull request 'New SQL API + SchemByUserAndType speedup' (#115) from schemSpeedup into master
Reviewed-on: #115 Reviewed-by: YoyoNow <jwsteam@nidido.de>
Dieser Commit ist enthalten in:
Commit
fa3e935b90
@ -71,7 +71,7 @@ public class Core extends JavaPlugin{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable(){
|
public void onDisable(){
|
||||||
SQL.closeConnection();
|
SQL.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Core getInstance() {
|
public static Core getInstance() {
|
||||||
|
@ -24,18 +24,18 @@ import org.bukkit.configuration.file.YamlConfiguration;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
|
||||||
public class SQL {
|
public class SQL {
|
||||||
|
|
||||||
private 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 Connection con;
|
||||||
|
private static String url;
|
||||||
|
private static String user;
|
||||||
|
private static String password;
|
||||||
|
|
||||||
static{
|
static{
|
||||||
File file = new File(Core.getInstance().getDataFolder(), "MySQL.yml");
|
File file = new File(Core.getInstance().getDataFolder(), "MySQL.yml");
|
||||||
@ -44,20 +44,47 @@ public class SQL {
|
|||||||
if(!file.exists())
|
if(!file.exists())
|
||||||
throw new SecurityException("SQL-ConfigFile not found!");
|
throw new SecurityException("SQL-ConfigFile not found!");
|
||||||
|
|
||||||
host = config.getString("HOST");
|
url = "jdbc:mysql://" + config.getString("HOST") + ":" + config.getString("PORT") + "/" + config.getString("DATABASE");
|
||||||
port = config.getString("PORT");
|
|
||||||
database = config.getString("DATABASE");
|
|
||||||
user = config.getString("USER");
|
user = config.getString("USER");
|
||||||
password = config.getString("PASSWORD");
|
password = config.getString("PASSWORD");
|
||||||
|
|
||||||
connect();
|
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 {
|
try {
|
||||||
con.close();
|
con.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new SecurityException("Could not close connection", 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 {
|
try {
|
||||||
prepare(qry, objects).executeUpdate();
|
prepare(qry, objects).executeUpdate();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
reconnect();
|
reset(e);
|
||||||
try {
|
try {
|
||||||
prepare(qry, objects).executeUpdate();
|
prepare(qry, objects).executeUpdate();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
@ -78,7 +105,7 @@ public class SQL {
|
|||||||
try {
|
try {
|
||||||
return prepare(qry, objects).executeQuery();
|
return prepare(qry, objects).executeQuery();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
reconnect();
|
reset(e);
|
||||||
try {
|
try {
|
||||||
return prepare(qry, objects).executeQuery();
|
return prepare(qry, objects).executeQuery();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
@ -91,7 +118,7 @@ public class SQL {
|
|||||||
try {
|
try {
|
||||||
return con.createBlob();
|
return con.createBlob();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
reconnect();
|
reset(e);
|
||||||
try {
|
try {
|
||||||
return con.createBlob();
|
return con.createBlob();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
@ -108,18 +135,66 @@ public class SQL {
|
|||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void connect() {
|
public static class Statement {
|
||||||
|
private static final List<Statement> statements = new ArrayList<>();
|
||||||
|
|
||||||
|
private final String sql;
|
||||||
|
private PreparedStatement st;
|
||||||
|
|
||||||
|
Statement(String sql) {
|
||||||
|
this.sql = sql;
|
||||||
|
statements.add(this);
|
||||||
try {
|
try {
|
||||||
con = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port + "/" + database + "?autoreconnect=true", user, password);
|
init();
|
||||||
if(con.isClosed())
|
|
||||||
throw new SQLException("Could not connect to database!");
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new SecurityException("No connection to database.", e);
|
reset(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void reconnect(){
|
private synchronized void init() throws SQLException {
|
||||||
closeConnection();
|
st = con.prepareStatement(sql);
|
||||||
connect();
|
}
|
||||||
|
|
||||||
|
<T> T select(ResultSetUser<T> 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> T prepare(SQLRunnable<T> 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> {
|
||||||
|
T use(ResultSet rs) throws SQLException;
|
||||||
|
}
|
||||||
|
|
||||||
|
private interface SQLRunnable<T> {
|
||||||
|
T run() throws SQLException;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ import java.util.zip.GZIPInputStream;
|
|||||||
|
|
||||||
public class Schematic {
|
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 int schemID;
|
||||||
private final String schemName;
|
private final String schemName;
|
||||||
private final int schemOwner;
|
private final int schemOwner;
|
||||||
@ -118,12 +120,12 @@ public class Schematic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static List<Schematic> getSchemsOfType(int schemOwner, SchematicType schemType){
|
public static List<Schematic> getSchemsOfType(int schemOwner, SchematicType schemType){
|
||||||
//Unsauber, dafür auch geaddede Schematics dabei
|
return getSchemsOfType.select(rs -> {
|
||||||
List<Schematic> schems = getSchemsAccessibleByUser(schemOwner);
|
List<Schematic> schematics = new ArrayList<>();
|
||||||
for(int i = schems.size()-1; i >= 0; i--)
|
while(rs.next())
|
||||||
if(!schems.get(i).getSchemType().equals(schemType))
|
schematics.add(new Schematic(rs));
|
||||||
schems.remove(i);
|
return schematics;
|
||||||
return schems;
|
}, schemType.toDB(), schemOwner, schemOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<Schematic> getAllSchemsOfType(SchematicType schemType){
|
public static List<Schematic> getAllSchemsOfType(SchematicType schemType){
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren