Refactor sql datastore

This commit is contained in:
Luck 2016-06-24 11:53:33 +01:00
parent e07a346e16
commit 34ca3b3c25
2 changed files with 217 additions and 159 deletions

View File

@ -76,7 +76,7 @@ public class FlatfileDatastore extends Datastore {
return success; return success;
} }
private void close(AutoCloseable closeable) { private static void close(AutoCloseable closeable) {
if (closeable == null) return; if (closeable == null) return;
try { try {
closeable.close(); closeable.close();

View File

@ -2,6 +2,8 @@ package me.lucko.luckperms.data.methods;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import lombok.AllArgsConstructor;
import lombok.Getter;
import me.lucko.luckperms.LuckPermsPlugin; import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.data.Datastore; import me.lucko.luckperms.data.Datastore;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
@ -21,7 +23,7 @@ import java.util.UUID;
import java.util.logging.Level; import java.util.logging.Level;
@SuppressWarnings("UnnecessaryLocalVariable") @SuppressWarnings("UnnecessaryLocalVariable")
public abstract class SQLDatastore extends Datastore { abstract class SQLDatastore extends Datastore {
private static final Type NM_TYPE = new TypeToken<Map<String, Boolean>>(){}.getType(); private static final Type NM_TYPE = new TypeToken<Map<String, Boolean>>(){}.getType();
@ -48,47 +50,75 @@ public abstract class SQLDatastore extends Datastore {
abstract Connection getConnection() throws SQLException; abstract Connection getConnection() throws SQLException;
private static void executeQuery(Connection connection, String query, Closer closer) throws SQLException { private static void close(AutoCloseable closeable) {
PreparedStatement preparedStatement = connection.prepareStatement(query); if (closeable == null) return;
closer.add(preparedStatement); try {
preparedStatement.execute(); closeable.close();
preparedStatement.close(); } catch (Exception e) {
e.printStackTrace();
}
} }
private boolean runQuery(Query query) { private boolean runQuery(QueryPS queryPS) {
boolean success = false; boolean success = false;
Connection connection = null; Connection connection = null;
Closer c = new Closer(); PreparedStatement preparedStatement = null;
try { try {
connection = getConnection(); connection = getConnection();
if (connection == null) { if (connection == null) {
throw new IllegalStateException("SQL connection is null"); throw new IllegalStateException("SQL connection is null");
} }
success = query.onRun(connection, c);
preparedStatement = connection.prepareStatement(queryPS.getQuery());
queryPS.onRun(preparedStatement);
preparedStatement.execute();
success = true;
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
success = false;
} finally { } finally {
c.closeAll(); close(preparedStatement);
if (connection != null) { close(connection);
try { }
connection.close(); return success;
} catch (SQLException e) { }
e.printStackTrace();
} private boolean runQuery(QueryRS queryRS) {
boolean success = false;
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = getConnection();
if (connection == null) {
throw new IllegalStateException("SQL connection is null");
} }
preparedStatement = connection.prepareStatement(queryRS.getQuery());
queryRS.onRun(preparedStatement);
preparedStatement.execute();
resultSet = preparedStatement.executeQuery();
success = queryRS.onResult(resultSet);
} catch (SQLException e) {
e.printStackTrace();
} finally {
close(resultSet);
close(preparedStatement);
close(connection);
} }
return success; return success;
} }
void setupTables(String... tableQueries) { void setupTables(String... tableQueries) {
boolean success = runQuery((connection, closer) -> { boolean success = true;
for (String s : tableQueries) { for (String q : tableQueries) {
executeQuery(connection, s, closer); if (!runQuery(new Query(q))) success = false;
} }
return true;
});
if (!success) { if (!success) {
plugin.getLogger().log(Level.SEVERE, "Error occurred whilst initialising the database. All connections are disallowed."); plugin.getLogger().log(Level.SEVERE, "Error occurred whilst initialising the database. All connections are disallowed.");
@ -100,19 +130,21 @@ public abstract class SQLDatastore extends Datastore {
@Override @Override
public boolean loadUser(UUID uuid) { public boolean loadUser(UUID uuid) {
User user = plugin.getUserManager().makeUser(uuid); User user = plugin.getUserManager().makeUser(uuid);
boolean success = runQuery((connection, closer) -> { boolean success = runQuery(new QueryRS(USER_SELECT) {
PreparedStatement preparedStatement = connection.prepareStatement(USER_SELECT); @Override
closer.add(preparedStatement); void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, uuid.toString()); preparedStatement.setString(1, uuid.toString());
}
ResultSet resultSet = preparedStatement.executeQuery();
closer.add(resultSet); @Override
if (resultSet.next()) { boolean onResult(ResultSet resultSet) throws SQLException {
user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); if (resultSet.next()) {
user.setName(resultSet.getString("name")); user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
return true; user.setName(resultSet.getString("name"));
return true;
}
return false;
} }
return false;
}); });
// User updating and loading should be done sync as permission attachments are updated // User updating and loading should be done sync as permission attachments are updated
@ -126,24 +158,30 @@ public abstract class SQLDatastore extends Datastore {
try { try {
user.setPermission(plugin.getConfiguration().getDefaultGroupNode(), true); user.setPermission(plugin.getConfiguration().getDefaultGroupNode(), true);
} catch (ObjectAlreadyHasException ignored) {} } catch (ObjectAlreadyHasException ignored) {}
boolean success = runQuery((connection, closer) -> {
PreparedStatement preparedStatement = connection.prepareStatement(USER_SELECT);
closer.add(preparedStatement);
preparedStatement.setString(1, user.getUuid().toString());
ResultSet resultSet = preparedStatement.executeQuery(); boolean success = runQuery(new QueryRS(USER_SELECT) {
closer.add(resultSet); @Override
if (!resultSet.next()) { void onRun(PreparedStatement preparedStatement) throws SQLException {
PreparedStatement preparedStatement1 = connection.prepareStatement(USER_INSERT); preparedStatement.setString(1, user.getUuid().toString());
closer.add(preparedStatement1); }
preparedStatement1.setString(1, user.getUuid().toString());
preparedStatement1.setString(2, user.getName()); @Override
preparedStatement1.setString(3, gson.toJson(user.getNodes())); boolean onResult(ResultSet resultSet) throws SQLException {
preparedStatement1.execute(); boolean success = true;
} else { if (!resultSet.next()) {
user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); success = runQuery(new QueryPS(USER_INSERT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, user.getUuid().toString());
preparedStatement.setString(2, user.getName());
preparedStatement.setString(3, gson.toJson(user.getNodes()));
}
});
} else {
user.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
}
return success;
} }
return true;
}); });
// User updating and loading should be done sync as permission attachments are updated // User updating and loading should be done sync as permission attachments are updated
@ -153,14 +191,13 @@ public abstract class SQLDatastore extends Datastore {
@Override @Override
public boolean saveUser(User user) { public boolean saveUser(User user) {
boolean success = runQuery((connection, closer) -> { boolean success = runQuery(new QueryPS(USER_UPDATE) {
PreparedStatement preparedStatement = connection.prepareStatement(USER_UPDATE); @Override
closer.add(preparedStatement); void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, user.getName()); preparedStatement.setString(1, user.getName());
preparedStatement.setString(2, gson.toJson(user.getNodes())); preparedStatement.setString(2, gson.toJson(user.getNodes()));
preparedStatement.setString(3, user.getUuid().toString()); preparedStatement.setString(3, user.getUuid().toString());
preparedStatement.execute(); }
return true;
}); });
return success; return success;
} }
@ -168,25 +205,28 @@ public abstract class SQLDatastore extends Datastore {
@Override @Override
public boolean createAndLoadGroup(String name) { public boolean createAndLoadGroup(String name) {
Group group = plugin.getGroupManager().makeGroup(name); Group group = plugin.getGroupManager().makeGroup(name);
boolean success = runQuery((connection, closer) -> { boolean success = runQuery(new QueryRS(GROUP_SELECT) {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SELECT); @Override
closer.add(preparedStatement); void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, group.getName()); preparedStatement.setString(1, group.getName());
}
ResultSet resultSet = preparedStatement.executeQuery();
closer.add(resultSet); @Override
boolean onResult(ResultSet resultSet) throws SQLException {
if (!resultSet.next()) { boolean success = true;
PreparedStatement preparedStatement1 = connection.prepareStatement(GROUP_INSERT); if (!resultSet.next()) {
closer.add(preparedStatement1); success = runQuery(new QueryPS(GROUP_INSERT) {
preparedStatement1.setString(1, group.getName()); @Override
preparedStatement1.setString(2, gson.toJson(group.getNodes())); void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement1.execute(); preparedStatement.setString(1, group.getName());
preparedStatement.setString(2, gson.toJson(group.getNodes()));
} else { }
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); });
} else {
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
}
return success;
} }
return true;
}); });
if (success) plugin.getGroupManager().updateOrSetGroup(group); if (success) plugin.getGroupManager().updateOrSetGroup(group);
@ -196,18 +236,20 @@ public abstract class SQLDatastore extends Datastore {
@Override @Override
public boolean loadGroup(String name) { public boolean loadGroup(String name) {
Group group = plugin.getGroupManager().makeGroup(name); Group group = plugin.getGroupManager().makeGroup(name);
boolean success = runQuery((connection, closer) -> { boolean success = runQuery(new QueryRS(GROUP_SELECT) {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SELECT); @Override
closer.add(preparedStatement); void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, name); preparedStatement.setString(1, name);
}
ResultSet resultSet = preparedStatement.executeQuery();
closer.add(resultSet); @Override
if (resultSet.next()) { boolean onResult(ResultSet resultSet) throws SQLException {
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE)); if (resultSet.next()) {
return true; group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
return true;
}
return false;
} }
return false;
}); });
if (success) plugin.getGroupManager().updateOrSetGroup(group); if (success) plugin.getGroupManager().updateOrSetGroup(group);
@ -217,18 +259,21 @@ public abstract class SQLDatastore extends Datastore {
@Override @Override
public boolean loadAllGroups() { public boolean loadAllGroups() {
List<Group> groups = new ArrayList<>(); List<Group> groups = new ArrayList<>();
boolean success = runQuery((connection, closer) -> { boolean success = runQuery(new QueryRS(GROUP_SELECT_ALL) {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_SELECT_ALL); @Override
closer.add(preparedStatement); void onRun(PreparedStatement preparedStatement) throws SQLException {
ResultSet resultSet = preparedStatement.executeQuery();
closer.add(resultSet);
while (resultSet.next()) {
Group group = plugin.getGroupManager().makeGroup(resultSet.getString("name"));
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
groups.add(group);
} }
return true;
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
while (resultSet.next()) {
Group group = plugin.getGroupManager().makeGroup(resultSet.getString("name"));
group.getNodes().putAll(gson.fromJson(resultSet.getString("perms"), NM_TYPE));
groups.add(group);
}
return true;
}
}); });
if (success) { if (success) {
@ -241,97 +286,110 @@ public abstract class SQLDatastore extends Datastore {
@Override @Override
public boolean saveGroup(Group group) { public boolean saveGroup(Group group) {
boolean success = runQuery((connection, closer) -> { boolean success = runQuery(new QueryPS(GROUP_UPDATE) {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_UPDATE); @Override
closer.add(preparedStatement); void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, gson.toJson(group.getNodes())); preparedStatement.setString(1, gson.toJson(group.getNodes()));
preparedStatement.setString(2, group.getName()); preparedStatement.setString(2, group.getName());
preparedStatement.execute(); }
return true;
}); });
return success; return success;
} }
@Override @Override
public boolean deleteGroup(Group group) { public boolean deleteGroup(Group group) {
boolean success = runQuery((connection, closer) -> { boolean success = runQuery(new QueryPS(GROUP_DELETE) {
PreparedStatement preparedStatement = connection.prepareStatement(GROUP_DELETE); @Override
closer.add(preparedStatement); void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, group.getName()); preparedStatement.setString(1, group.getName());
preparedStatement.execute(); }
return true;
}); });
if (success) plugin.getGroupManager().unloadGroup(group); if (success) plugin.getGroupManager().unloadGroup(group);
return success; return success;
} }
@Override @Override
public boolean saveUUIDData(String username, UUID uuid) { public boolean saveUUIDData(String username, UUID uuid) {
boolean success = runQuery((connection, closer) -> { boolean success = runQuery(new QueryRS(UUIDCACHE_SELECT) {
PreparedStatement preparedStatement = connection.prepareStatement(UUIDCACHE_SELECT); @Override
closer.add(preparedStatement); void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, username); preparedStatement.setString(1, username);
ResultSet resultSet = preparedStatement.executeQuery();
closer.add(resultSet);
PreparedStatement preparedStatement1;
if (resultSet.next()) {
preparedStatement1 = connection.prepareStatement(UUIDCACHE_UPDATE);
closer.add(preparedStatement1);
preparedStatement1.setString(1, uuid.toString());
preparedStatement1.setString(2, username);
} else {
preparedStatement1 = connection.prepareStatement(UUIDCACHE_INSERT);
closer.add(preparedStatement1);
preparedStatement1.setString(1, username);
preparedStatement1.setString(2, uuid.toString());
} }
preparedStatement1.execute(); @Override
return true; boolean onResult(ResultSet resultSet) throws SQLException {
boolean success;
if (resultSet.next()) {
success = runQuery(new QueryPS(UUIDCACHE_UPDATE) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, uuid.toString());
preparedStatement.setString(2, username);
}
});
} else {
success = runQuery(new QueryPS(UUIDCACHE_INSERT) {
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
preparedStatement.setString(1, username);
preparedStatement.setString(2, uuid.toString());
}
});
}
return success;
}
}); });
return success; return success;
} }
@Override @Override
public UUID getUUID(String username) { public UUID getUUID(String username) {
final UUID[] uuid = {null}; final UUID[] uuid = {null};
boolean success = runQuery((connection, closer) -> {
PreparedStatement preparedStatement = connection.prepareStatement(UUIDCACHE_SELECT);
closer.add(preparedStatement);
preparedStatement.setString(1, username);
ResultSet resultSet = preparedStatement.executeQuery(); boolean success = runQuery(new QueryRS(UUIDCACHE_SELECT) {
closer.add(resultSet); @Override
if (resultSet.next()) { void onRun(PreparedStatement preparedStatement) throws SQLException {
uuid[0] = UUID.fromString(resultSet.getString("uuid")); preparedStatement.setString(1, username);
return true; }
@Override
boolean onResult(ResultSet resultSet) throws SQLException {
if (resultSet.next()) {
uuid[0] = UUID.fromString(resultSet.getString("uuid"));
return true;
}
return false;
} }
return false;
}); });
return success ? uuid[0] : null; return success ? uuid[0] : null;
} }
interface Query { private class Query extends QueryPS {
boolean onRun(Connection connection, Closer closer) throws SQLException; Query(String query) {
super(query);
}
@Override
void onRun(PreparedStatement preparedStatement) throws SQLException {
// Do nothing
}
} }
private class Closer { @Getter
private final List<AutoCloseable> objects = new ArrayList<>(); @AllArgsConstructor
private abstract class QueryPS {
private final String query;
abstract void onRun(PreparedStatement preparedStatement) throws SQLException;
}
public void add(AutoCloseable a) { @Getter
objects.add(a); @AllArgsConstructor
} private abstract class QueryRS {
private final String query;
void closeAll() { abstract void onRun(PreparedStatement preparedStatement) throws SQLException;
objects.stream().filter(a -> a != null).forEach(a -> { abstract boolean onResult(ResultSet resultSet) throws SQLException;
try {
a.close();
} catch (Exception ignored) {}
});
}
} }
} }