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
|
||||
public void onDisable(){
|
||||
SQL.closeConnection();
|
||||
SQL.close();
|
||||
}
|
||||
|
||||
public static Core getInstance() {
|
||||
|
@ -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<Statement> 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> 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;
|
||||
}
|
||||
}
|
||||
|
||||
private static void reconnect(){
|
||||
closeConnection();
|
||||
connect();
|
||||
}
|
||||
}
|
||||
|
@ -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<Schematic> getSchemsOfType(int schemOwner, SchematicType schemType){
|
||||
//Unsauber, dafür auch geaddede Schematics dabei
|
||||
List<Schematic> 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<Schematic> schematics = new ArrayList<>();
|
||||
while(rs.next())
|
||||
schematics.add(new Schematic(rs));
|
||||
return schematics;
|
||||
}, schemType.toDB(), schemOwner, schemOwner);
|
||||
}
|
||||
|
||||
public static List<Schematic> getAllSchemsOfType(SchematicType schemType){
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren