2016-01-11 3 views
1

У меня есть вариант использования, когда я построю свой результат, соединяя две таблицы ITEM и ITEM_DESCRIPTION. Оттуда я беру несколько столбцов, которые затем я хотел бы удобно преобразовать в список объектов. В моем случае эти объекты фактически являются объектами DTO, но, конечно, они могут быть и бизнес-объектами.Как я могу использовать inGroups(), если возвращаемый тип не является известным типом?

Это так, как я делаю это сейчас:

public Map<Long, List<StoreItemDTO>> getItems(Long storeId) { 

    LOGGER.debug("getItems"); 

    // Get all item_ids for the store 

    SelectHavingStep<Record1<Long>> where = this.ctx 
     .select(STORE_ITEM.ID) 
     .from(STORE_ITEM) 
     .where(STORE_ITEM.STORE_ID.eq(storeId)) 
     // GROUP BY store_item.id 
     .groupBy(STORE_ITEM.ID); 

    // Get all store_item_details according to the fetched item_ids 

    TableLike<?> storeItemDetails = this.ctx 
     .select(
       STORE_ITEM_DETAILS.ID, 
       STORE_ITEM_DETAILS.STORE_ITEM_ID, 
       STORE_ITEM_DETAILS.NAME, 
       STORE_ITEM_DETAILS.DESCRIPTION, 
       STORE_ITEM_DETAILS.STORE_LANGUAGE_ID 
       ) 
     .from(STORE_ITEM_DETAILS) 
     .where(STORE_ITEM_DETAILS.STORE_ITEM_ID.in(where)) 
     .asTable("storeItemDetails"); 

    // Join the result and use 

    Field<Long> itemIdField = STORE_ITEM.ID.as("item_id"); 

    Result<?> fetch = this.ctx 
     .select(
       STORE_ITEM.ID.as("item_id"), 
       itemIdField, 
       storeItemDetails.field(STORE_ITEM_DETAILS.ID), 
       storeItemDetails.field(STORE_ITEM_DETAILS.NAME), 
       storeItemDetails.field(STORE_ITEM_DETAILS.DESCRIPTION), 
       storeItemDetails.field(STORE_ITEM_DETAILS.STORE_LANGUAGE_ID)      
       ) 
     .from(STORE_ITEM) 
     .join(storeItemDetails) 
     .on(storeItemDetails.field(STORE_ITEM_DETAILS.STORE_ITEM_ID).eq(STORE_ITEM.ID)) 
     .fetch(); 

    Map<Long, ?> groups = fetch.intoGroups(STORE_ITEM.ID); 

    return null; 
} 

Как вы можете видеть, результат должен быть список элементов, где каждый элемент имеет запись-детали на разных языках:

StoreItemDTO 
- Long id 
    // Maps language-id to item details 
- Map<Long, StoreItemDetails> itemDetails 

StoreItemDetails 
- Long id 
- String name 
- String description 

Я не смог найти версию intoGroups(), которая вернет полезный тип. Я мог представить себе что-то вроде Map<Long, List<Record>>, но я не могу этого сделать.

Однако есть intoGroups(RecordMapper<? super R, K> keyMapper), который мог бы быть тем, кого я ищу. Если бы mapper также позволил мне преобразовать результирующие записи в пользовательский объект, например MyCustomPojo, тогда я мог бы легко и удобно получать и преобразовывать данные. Я не знаю, насколько это возможно. Что-то вроде:

public static class MyCustomPojo { 
    public Long itemId; 
    // etc. 
} 

// .. 

Map<Long, List<MyCustomPojo>> result = fetch.intoGroups(STORE_ITEM.ID, new RecordMapper<Record, List<MyCustomPojo>>() { 
    @Override 
    public List<MyCustomPojo> map(List<Record> record) { 
     // 'record' is grouped by STORE_ITEM.ID 
     // Now map each 'record' into every item of each group .. 
     return resultList; 
    } 
}); 

Но, к сожалению, компилятор допускает только

fetch.intoGroups(new RecordMapper<Record, Result<?>>() { 
    @Override 
    public Result<?> map(Record record) { 
     return null; 
    } 
}); 

ответ

1

После некоторого возиться с компилятором, то получается, что это может быть сделано.

мне пришлось «обмануть» немного объявляя мою полученную карту, как final снаружи анонимным, и я на самом деле не «с помощью» параметр keyMapper, как я только что вернулся null.

Это то, что я придумал:

public Map<Long, StoreItemDTO> getItems(Long storeId) { 

    // Get all item_ids for the store 

    SelectHavingStep<Record1<Long>> where = this.ctx 
     .select(STORE_ITEM.ID) 
     .from(STORE_ITEM) 
     .where(STORE_ITEM.STORE_ID.eq(storeId)) 
     .groupBy(STORE_ITEM.ID); 

    // Get all store_item_details according to the fetched item_ids 

    TableLike<?> storeItemDetails = this.ctx 
     .select(
       STORE_ITEM_DETAILS.ID, 
       STORE_ITEM_DETAILS.STORE_ITEM_ID, 
       STORE_ITEM_DETAILS.NAME, 
       STORE_ITEM_DETAILS.DESCRIPTION, 
       STORE_ITEM_DETAILS.STORE_LANGUAGE_ID 
       ) 
     .from(STORE_ITEM_DETAILS) 
     .where(STORE_ITEM_DETAILS.STORE_ITEM_ID.in(where)) 
     .asTable("storeItemDetails"); 

    // Join the result and use 

    final Field<Long> itemIdField = STORE_ITEM.ID.as("item_id"); 

    Result<?> fetch = fetch = this.ctx 
     .select(
       itemIdField, 
       storeItemDetails.field(STORE_ITEM_DETAILS.ID), 
       storeItemDetails.field(STORE_ITEM_DETAILS.NAME), 
       storeItemDetails.field(STORE_ITEM_DETAILS.DESCRIPTION), 
       storeItemDetails.field(STORE_ITEM_DETAILS.STORE_LANGUAGE_ID) 
       ) 
     .from(STORE_ITEM) 
     .join(storeItemDetails) 
     .on(storeItemDetails.field(STORE_ITEM_DETAILS.STORE_ITEM_ID).eq(STORE_ITEM.ID)) 
     .fetch(); 

    final Map<Long, StoreItemDTO> itemIdToItemMap = new HashMap<>(); 

    fetch.intoGroups(
      record -> { 
       Long itemDetailsId = record.getValue(STORE_ITEM_DETAILS.ID); 
       // ... sake of compactness 

       StoreItemDetailsDTO storeItemDetailsDto = new StoreItemDetailsDTO(); 
       storeItemDetailsDto.setId(itemDetailsId); 
       // ... sake of compactness 

       Long itemId = record.getValue(itemIdField); 

       StoreItemDTO storeItemDto = new StoreItemDTO(); 
       storeItemDto.setId(itemId); 
       storeItemDto.getItemDetailsTranslations().put(languageId, storeItemDetailsDto); 

       StoreItemDTO itemDetailsList = itemIdToItemMap.get(itemId); 

       if(itemDetailsList == null) { 
        itemDetailsList = new StoreItemDTO(); 
        itemIdToItemMap.put(itemId, itemDetailsList); 
       } 

       itemDetailsList.getItemDetailsTranslations().put(languageId, storeItemDetailsDto); 

       return null; 
      }); 

    return itemIdToItemMap; 
} 

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

Смежные вопросы