Skip to content

Commit

Permalink
feat(database): optimize querySQL method
Browse files Browse the repository at this point in the history
Refactor the `querySQL` method in `MySQLEntityRepository` to use prepared statements for better performance and security. This change ensures that SQL statements are properly parameterized, preventing SQL injection vulnerabilities.
  • Loading branch information
GeorgeV220 committed Jun 20, 2024
1 parent 561a925 commit c427ec5
Showing 1 changed file with 49 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
Expand Down Expand Up @@ -102,15 +103,13 @@ private void executeStatement(String statement) {
}
}

private @Nullable ResultSet querySQL(String statement) {
try (Connection connection = this.database.getConnection()) {
private @Nullable PreparedStatement querySQL(String statement) {
try {
Connection connection = this.database.getConnection();
if (connection == null || connection.isClosed()) {
try (Connection newConnection = this.database.openConnection()) {
return newConnection.createStatement().executeQuery(statement);
}
} else {
return connection.createStatement().executeQuery(statement);
connection = this.database.openConnection();
}
return connection.prepareStatement(statement);
} catch (SQLException | ClassNotFoundException e) {
this.logger.log(Level.SEVERE, "[EntityRepository]:", e);
return null;
Expand All @@ -130,22 +129,27 @@ public CompletableFuture<V> load(@NotNull String entityId) {
}
return CompletableFuture.supplyAsync(() -> {
String statement = "SELECT * FROM " + this.tableName + " WHERE _id = '" + escapeSql(entityId) + "'";

try (ResultSet resultSet = this.querySQL(statement)) {
if (resultSet == null) {
this.logger.log(Level.SEVERE, "Failed to load entity with ID: " + entityId + " because the result set was null.");
try (PreparedStatement stmt = querySQL(statement)) {
if (stmt == null) {
this.logger.log(Level.SEVERE, "Failed to create statement for entity ID: " + entityId);
return null;
}
if (resultSet.next()) {
this.checkForConstructorWithSingleString(this.entityClass);
V entity = this.entityClass.getConstructor(String.class).newInstance(entityId);
for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
String columnName = resultSet.getMetaData().getColumnName(i + 1);
Object columnValue = resultSet.getObject(i + 1);
entity.setValue(columnName, columnValue);
try (ResultSet resultSet = stmt.executeQuery()) {
if (resultSet == null) {
this.logger.log(Level.SEVERE, "Failed to load entity with ID: " + entityId + " because the result set was null.");
return null;
}
if (resultSet.next()) {
this.checkForConstructorWithSingleString(this.entityClass);
V entity = this.entityClass.getConstructor(String.class).newInstance(entityId);
for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
String columnName = resultSet.getMetaData().getColumnName(i + 1);
Object columnValue = resultSet.getObject(i + 1);
entity.setValue(columnName, columnValue);
}
this.loadedEntities.append(entityId, entity);
return entity;
}
this.loadedEntities.append(entityId, entity);
return entity;
}
} catch (SQLException | NoSuchMethodException | InvocationTargetException | InstantiationException |
IllegalAccessException | NoSuchConstructorException e) {
Expand Down Expand Up @@ -186,16 +190,23 @@ public CompletableFuture<Boolean> exists(@NotNull String entityId, boolean check
}
if (checkDb) {
String statement = "SELECT COUNT(*) FROM " + this.tableName + " WHERE _id = '" + escapeSql(entityId) + "'";
try (ResultSet resultSet = this.querySQL(statement)) {
if (resultSet == null) {
this.logger.log(Level.SEVERE, "Failed to check if entity with ID: " + entityId + " exists because the result set was null.");
try (PreparedStatement stmt = querySQL(statement)) {
if (stmt == null) {
this.logger.log(Level.SEVERE, "Failed to create statement for entity ID: " + entityId);
return false;
}
resultSet.next();
int count = resultSet.getInt(1);
return forceLoad ? this.load(entityId) != null : count > 0;
try (ResultSet resultSet = stmt.executeQuery()) {
if (resultSet == null) {
this.logger.log(Level.SEVERE, "Failed to check if entity with ID: " + entityId + " exists because the result set was null.");
return false;
}
resultSet.next();
int count = resultSet.getInt(1);
return forceLoad ? this.load(entityId) != null : count > 0;
}
} catch (SQLException e) {
this.logger.log(Level.SEVERE, "[EntityRepository]:", e);
return false;
}
}
return false;
Expand Down Expand Up @@ -230,13 +241,19 @@ public CompletableFuture<Void> delete(@NotNull String entityId) {
@Override
public void loadAll() {
String statement = "SELECT * FROM " + this.tableName;
try (ResultSet resultSet = this.querySQL(statement)) {
if (resultSet == null) {
this.logger.log(Level.SEVERE, "Failed to load all entities because the result set was null.");
try (PreparedStatement preparedStatement = this.querySQL(statement)) {
if (preparedStatement == null) {
this.logger.log(Level.SEVERE, "Failed to create statement for loading all entities.");
return;
}
while (resultSet.next()) {
this.load(resultSet.getString("_id"));
try (ResultSet resultSet = preparedStatement.executeQuery()) {
if (resultSet == null) {
this.logger.log(Level.SEVERE, "Failed to load all entities because the result set was null.");
return;
}
while (resultSet.next()) {
this.load(resultSet.getString("_id"));
}
}
} catch (SQLException e) {
this.logger.log(Level.SEVERE, "[EntityRepository]:", e);
Expand All @@ -248,7 +265,7 @@ public void loadAll() {
*/
@Override
public void saveAll() {
for (V entity :this.loadedEntities.values()) {
for (V entity : this.loadedEntities.values()) {
this.save(entity);
}
}
Expand Down

0 comments on commit c427ec5

Please sign in to comment.