преобразовать ResultSet в универсальный класс, где конструктор класса определяется с помощью фабрики - PullRequest
0 голосов
/ 11 октября 2018

Я определил метод для анализа результата запроса выбора MySQl в общий класс.

Этот метод выглядит следующим образом:

public <T> List<T> selectFromDb(Class<T> _class, String tableName,
                                     String searchKeyName, String searchKeyValue)
    throws SQLException, IllegalAccessException,
    InstantiationException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException {

    List<T> listDbData = new ArrayList<>();

    final String selectQuery = String.format("select * from %s.%s where %s = ?;",
        schemaName, tableName, searchKeyName);
    PreparedStatement selectStatement = connection.prepareStatement(selectQuery);

    try {
        selectStatement.setString(1, searchKeyValue);
        ResultSet result = selectStatement.executeQuery();
        while (result.next()) {

            T t = _class.getDeclaredConstructor(ResultSet.class).newInstance(result);

            listDbData.add(t);
        }

        selectStatement.close();
    }catch (SQLException e) {
        log.error("Query failed:" + selectQuery);
        throw e;
    } finally {
        selectStatement.close();
    }

    return listDbData;
}

Я использую его для выполнения выбора надве таблицы базы данных, для которых я определил схему.

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

   @Getter //lombok
   @Setter
    public class C extends A {
        private String varA;
        private String varB;
        private String varC;


       public C(String s1, String s2) {
        ...
        ...
       }

       public C (ResultSet resultSet) {
       ....
       ...
       }

       //Other class methods

    }

Теперь я определил фабрику, чтобы сделать класс неизменным.Я хочу знать, как изменить код selectFromDb для обработки измененного класса.

public class CFactory {

      public static C from(String s1, String s2) {
        C c;
        ...
        ...

        return c;
       }

       public static C from(ResultSet resultSet) throws SQLException {
         C c;
         ....
         ...
         return c; 
         } 
}
@Builder
@Getter //lombok
public class C extends A{

        private final String varA;
        private final String varB;
        private final String varC;

        ....
        ....

}

Спасибо.Swagatika

1 Ответ

0 голосов
/ 11 октября 2018

Вы объявляете это

public <T> List<T> selectFromDb(Function<ResultSet,T> factory, String tableName,
                                 String searchKeyName, String searchKeyValue)

Вы создаете экземпляр через

while (result.next()) {

    T t = factory.apply(result);

    listDbData.add(t);
}

, который вы вызываете по

selectFromDb(CFactory::from, searchKeyName, searchKeyValue);

Фактически, вы могли бы сделать этово-первых, и передал YourClass::new в качестве ссылки на метод для конструктора, который вы получили с помощью отражения в вашем коде.

В качестве примечания вы можете оставить конструктор - это не сделает ваш класс менее неизменным,Кроме того, почему бы не сделать фабричные методы static?(мой пример кода предполагает, что они есть)

...