Анализ результатов из таблицы базы данных в общую коллекцию

#java #generics #collections

#java #общие сведения #Коллекции

Вопрос:

У меня есть метод на Java, который анализирует некоторые данные из базы данных

 ArrayList<Object> nodeList = new ArrayList<Object>();

public void parseResults() throws SQLException, ListEmptyException, NoRecognisableCharacterException{
//        parses records from a query. ONLY ONE COLUMN
    while(getResultSet().next()){    
        for(int i = 1; i <= getNumberOfColumns(); i  ){
            switch(getColumnType()){
//According to the datatype, I call the proper method get[DataType] of resultSet
                case 0:throw new ListEmptyException();
                case 4:nodeList.add(getResultSet().getInt(i));break;
                case 12:nodeList.add(getResultSet().getString(i).trim());break;
                default:throw new NoRecognisableCharacterException();
            }
        }
    }
}
  

Мне сказали не использовать ArrayList<Object> для хранения данных другого типа. Я должен создать объект, который вместо этого анализирует соответствующий тип данных. Я не хочу перегружать метод для каждого отдельного типа данных (их много), ни создавать отдельные классы, которые просто изменяют один get[DataType] метод, ни иметь этот switch цикл внутри for цикла, ни иметь множественные экземпляры NodeList в соответствии с типом данных. Есть ли способ заставить этот метод работать для каждого типа данных? Должны ли в этом случае использоваться общие файлы? Заранее благодарю вас.

Комментарии:

1. Я не уверен, что понимаю вашу идею, но правильный способ обработки / анализа разных данных из базы данных — использовать отдельные классы для разных данных, загруженных из разных таблиц. Чрезмерная унификация здесь противоречит цели и не помогает и не делает ваш код чистым.

Ответ №1:

Вы можете обернуть свой объект resultset в класс, подобный этому:

 public class ObjectWrapper implements Wrapper {
    private Object wrappedObject;

    public ObjectWrapper(Object wrappedObject) {
        this.wrappedObject = wrappedObject;
    }

    @SuppressWarnings("unchecked")
    public <T> T unwrap(Class<T> paramClass) {
        return (T) wrappedObject;
    }

    public boolean isWrapperFor(Class<?> paramClass) {
        return paramClass.isInstance(wrappedObject);
    }

    public static Wrapper wrap(ResultSet rs, int column, int columnType) throws SQLException {
        if (columnType == 0) {
            return new EmptyListExceptionWrapper();
        } else {
            return new ObjectWrapper(rs.getObject(column));
        }
    }
}
  

и класс для управления исключениями:

 public class EmptyListExceptionWrapper implements Wrapper {
    @Override
    public <T> T unwrap(Class<T> paramClass) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> paramClass) throws SQLException {
        return false;
    }
}
  

Тогда у вас есть

 ArrayList<Wrapper> wrapper = new ArrayList<Wrapper>;
  

Ваш код будет:

 while(getResultSet().next()){    
    for(int i = 1; i <= getNumberOfColumns(); i  ){
        wrappers.add(ObjectWrapper.wrap(getResultSet(), i, getColumnType()));
    }
}
  

Комментарии:

1. Это было именно то, что я искал!! Но он возвращает такие имена, как dataBaseConnection.ObjectWrapper@179d3b25 … как я должен это исправить?

2. Вы должны переопределить метод toString.

3. Все эти классы-оболочки для меня совершенно новые… не были бы вы так любезны рассказать мне, как именно переопределить toString() метод для этого?

4. @Override public String toString() { return wrappedObject.toString(); }