Использование запроса внутри RowMapper

В java я бы сделал что-то вроде ниже, чтобы выполнить итерацию resultset и сформировать запрос,

public Map<String, List<MODEL>> fun(){
Map<String, List<MODEL>> map = new TreeMap<String, List<MODEL>>();      
        LinkedHashSet<String> set = new LinkedHashSet<String>();

            String sql = "select distinct(column) from table where conditions orderby column ";
            ResultSet rslt = stmt.executeQuery(sql);
            while (rslt.next()) {
                al.add(rslt.getString(1));
            }
            for (String s : al) {           
                List<MODEL> list = new ArrayList<MODEL>();
                String sql2 = "select * from table where column="+s;
                ResultSet rslt2 = stmt.executeQuery(sql2);
                while (rslt2.next()) {
                    MODEL obj = new MODEL();
                    // set values to setters from resultset
                    list.add(obj);
                }
                map.put(s, list);
            }
            return map;
            }

причина, по которой я использовал отдельный запрос, я добавляю значения к ключу карты и их соответствующие значения (как список) к значениям карты. ПРИМЕЧАНИЕ (В результат имеет повторяющиеся значения column1), но мне нужно сохранить их в качестве ключа карты и, следовательно, сделать его уникальным. также мне нужны все связанные значения, чтобы заполнить список

Как я могу достичь той же функциональности, используя JdbcTemplate,

Заранее спасибо

Ответ 1

Как сказал @geoand, лучше всего (будь то в прямом коде JDBC или использовании JDBCTemplate) было бы сделать один запрос с помощью Join.

Если, как вы упомянули в комментариях, вы абсолютно уверены, что набор результатов из первого запроса всегда будет небольшим (сомнительным), тогда вы можете сохранить значения, полученные из первого запроса в списке, и затем выполните второй запрос с предложением "in", используя список в качестве параметра. Это приведет к двум запросам.

В любом случае, вы действительно не хотите делать отдельный запрос для каждого элемента, возвращаемого из первого запроса, поскольку это будет довольно медленно, даже для небольшого количества элементов. Но если вы чувствуете, что вы должны, затем сохраните результаты первого запроса в списке и затем выполните другой запрос для каждого элемента в списке.

TL;DR; Нет, JDBCTemplate не обеспечивает механизм для того, чтобы делать то, что вы хотите, в основном потому, что он обычно считается каноническим примером анти-шаблона программирования.

Ответ 2

Как заявлено несколькими людьми, ваше решение неэффективно, хотя оно может работать, вы в основном попадаете в ловушку проблемы 1 + N select. 1 для получения некоторого id и следующего для каждого id другого запроса (следовательно, выбирается 1 + N).

Лучше всего написать один запрос, который забирает все за один раз. Глядя на ваш код, у вас есть следующие 2 запроса, которые, по внешнему виду, работают в одной таблице.

String sql1 = "select distinct(column) from table where conditions orderby column ";
String sql2 = "select * from table where column="+s

Теперь вы можете либо сделать первый запрос подзапросом для второго запроса

String sql = "select * from table where column in (select distinct(column) from table where conditions) order by column";

Однако, опять же, по внешнему виду, было бы возможно (или, может быть, еще проще) просто поместить предложение where во второй запрос.

String sql = "select * from table where conditions order by column";

Теперь вы, возможно, получите для своего ключа (в Map) несколько значений. Вы можете сделать две вещи: либо использовать цикл ResultSetExtractor по результатам самостоятельно, либо использовать RowCallbackHandler, который выполняет итерацию для вас.

То, что вам нужно сделать, это просто повторить результаты (или позволить JdbcTemplate сделать это для вас), для вашего ключевого столбца проверьте Map, если a List уже существует. Если он добавляет строку, если она не создает сначала List и добавляет ее в результат Map.

public Map<String, List<MODEL>> fun(){
    final Map<String, List<MODEL>> map = new TreeMap<String, List<MODEL>>();      

    String sql = "select * from table where conditions order by column";
    getJdbcTemplate().query(sql, new RowCallbackHandler() {
        public void processRow(ResultSet resultSet) throws SQLException {
            String key = rs.getString("column");
            List rows = map.get(key);
            if (rows == null) {
                rows = new new ArrayList<MODEL>();
                map.put(key, rows);
            }
             MODEL obj = new MODEL();
            // set values to setters from resultset
            rows.add(obj);
        }, "arguments"); 
    return map;
}

Другое решение, которое будет работать только в том случае, если "столбец" также является частью класса MODEL. Таким образом, вы можете использовать RowMapper и получить List для всех объектов MODEL и впоследствии выполнить разбиение. Вы можете использовать Google Guava, чтобы сделать это немного проще, или если вы работаете на Java 8, вы можете использовать для этого новые потоки api.