Wpis z mikrobloga

#java
Mam pytanie. Posiadam taką klasę pomocniczą do testów:

@Component
public class SessionChecker {

private final DataSource dataSource;

public SessionChecker(DataSource dataSource) {
this.dataSource = dataSource;
}

public boolean checkExistence(String sessionId) {
try {
String query = "SELECT COUNT(*) FROM sessions WHERE session_id = ?";

try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(query)) {

statement.setString(1, sessionId);

ResultSet resultSet = statement.executeQuery();

return resultSet.next() && resultSet.getInt(1) > 0;
}
} catch (SQLException e) {
throw new RuntimeException("Error during checking if session exists " + e.getMessage(), e);
}
}

public boolean userHasActiveSessions(int userId) {
try {
String query = "SELECT COUNT(*) FROM sessions WHERE user_id = ?";

try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(query)) {

statement.setInt(1, userId);

try (ResultSet resultSet = statement.executeQuery()) {
return resultSet.next() && resultSet.getInt(1) > 0;
}
}
} catch (SQLException e) {
throw new RuntimeException("Error during checking if user has active sessions: " + e.getMessage(), e);
}
}
}

Czy zamiast tych dwóch metod mogę napisać to tak? Taki zapis będzie dobry?

@Component
public class SessionChecker {

private final DataSource dataSource;

public SessionChecker(DataSource dataSource) {
this.dataSource = dataSource;
}

public boolean sessionExist(String sessionId) {
String query = "SELECT COUNT(*) FROM sessions WHERE session_id = ?";
return checkExistence(query, sessionId);
}

public boolean userHasActiveSession(int userId) {
String query = "SELECT COUNT(*) FROM sessions WHERE user_id = ?";
return checkExistence(query, userId);
}

private boolean checkExistence(String query, Object value) {
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(query)) {

if (value instanceof Integer) {
statement.setInt(1, (Integer) value);
} else if (value instanceof String) {
statement.setString(1, (String) value);
}

ResultSet resultSet = statement.executeQuery();
return resultSet.next() && resultSet.getInt(1) > 0;
} catch (SQLException e) {
throw new RuntimeException("Error during checking existence: " + e.getMessage(), e);
}
}
}

Można to zrobić jakoś lepiej?
  • 3
  • Odpowiedz
@Kamishimi: Jeżeli to jest klasa która będzie dostępna tylko w Twoim katalogu z testami, to pewnie może być. Jeżeli natomiast miałaby być dostępna w głównym kodzie no to tak średnio bo całkowicie tracisz type-safety w tym miejscu. W miejscu drugiego parametru można przekazywać wtedy dosłownie wszystko i kompilator się nie zająknie.

Zamiast tego na Twoim miejscu celowałbym w sygnaturę private boolean checkExistence(String query, PreparedStatement statement). Wtedy każda z publicznych metod
  • Odpowiedz
@Kamishimi: Może:

checkExistence(String query, Consumer<PreparedStatement> propertySetter) {
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(query)) {
propertySetter.accept(statement);
ResultSet resultSet = statement.executeQuery();
return resultSet.next() && resultSet.getInt(1) > 0;
} catch (SQLException e) {
throw new RuntimeException("Error during checking existence: " + e.getMessage(), e);
}

public boolean userHasActiveSession(int userId) {
String query = "SELECT COUNT(*) FROM sessions WHERE user_id = ?";
return checkExistence(query, st -> st.setInt(1, userId));
}

public boolean sessionExist(String sessionId)
  • Odpowiedz