Создать общий метод "getColumn" для класса базы данных (Java) - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть класс Database, который инкапсулирует функциональность java.sql.* классов.По сути, вы создаете подкласс для создания соединения с определенной базой данных, а затем можете использовать его методы для выполнения общих операций.

Одна операция, которую я хотел бы реализовать, - это метод getColumn().Если ожидаемый столбец базы данных представляет собой тип данных String, я мог бы сделать следующее:

public List<String> getColumn(String sql) throws SQLException
{
    List<String> results = new ArrayList<>();
    ResultSet rs = _stmt.executeQuery(sql);
    while (rs.next())
    {
        results.add(rs.getString(1));
    }
    return results;
}

Но я хотел бы обобщить этот метод с параметром шаблона и использовать правильный метод ResultSet.get* для заполнения ArrayList.

Примерно так:

public <T> List<T> getColumn(String sql) throws SQLException
{
    List<T> results = new ArrayList<>();
    ResultSet rs = _stmt.executeQuery(sql);
    while (rs.next())
    {
        // if T is String, do:
        // results.add(rs.getString(1));
        // if T is Integer, do:
        // results.add(rs.getInt(1));
        // etc.
    }
    return results;

Я уверен, что должен быть элегантный способ сделать это.Мысли?Я поступаю об этом неправильно?}

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Распространенной ошибкой является попытка метода с сигнатурой, например:

<T> T fn()

В Java нет способа узнать в вызове fn что T.Возможны варианты возврата null, небезопасного приведения объекта, который может быть или не быть T, или выдачи исключения.Если у вас есть что-то похожее, но тип возврата List<T>, единственное, что вы можете сохранить в этом списке, это null.

Так что же делать.Обычно вы передаете аргумент для создания требуемого типа.Функциональный объект, например.(Я бы использовал java.util.function.Function, но мешали проверенные исключения.)

List<String> names = getColumn(
    "SELECT [...]",
    (result, column) -> result.getString(column)
);
[...]

interface ResultFunction<T> {
    T get(ResultSet results, int column) throws SQLException;
}

public <T> List<T> getColumn(
    String sql, ResultFunction<T> function
) throws SQLException {
    List<T> values = new ArrayList<>();
    try (ResultSet result = _stmt.executeQuery(sql)) {
        while (result.next()) {
            values.add(function.get(result, 1));
        }
    }
    return values;
}

Возможно, вы захотите расширить функциональность ResultFunction и, возможно, использовать перечисления.

0 голосов
/ 27 ноября 2018

Вот один из способов сделать это,

public <T> List<T> getColumn(String sql) throws SQLException {
    List<T> results = new ArrayList<>();
    ResultSet rs = _stmt.executeQuery(sql);
    while (rs.next()) {
        @SuppressWarnings("unchecked")
        final T colVal = (T) rs.getObject(1);
        results.add(colVal);
    }
    return results;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...