Java Play Framework с использованием Find и JPQL для создания списка объектов с дубликатами из списка строк - PullRequest
2 голосов
/ 17 марта 2012

Так что я новичок в Java, и Play все еще время от времени путается в квазиобъектно-ориентированном программировании ...

Мне нужно преобразовать строку с разделителями с повторяющимися значениями в список объектов, также с этимиповторяющиеся значения в том же порядке, что и строка.

Пример:

У меня есть форма, в которой пользователь отправляет строку, разделенную пробелом.Например:

http://www.feedme.com? Еда = яблоко + апельсин + банан + яблоко + виноград + яблоко

, который идет в

public static List<Food> getFoodList(String foodString) {
    foodString = foodString.trim();
    List<String> foods = Arrays.asList(foodString.split("\\s+")); 
    List<Food> foodList = Food.find("name IN (:foods)").bind("foods", foods).fetch();
    return foodList;
}

Я печатаю цикл списка строк на экране и получаю ожидаемое: яблоко апельсин банан яблоко грейпфрут

Я печатаю значение Food.name для каждого в цикле foodList и получаю: Grape Apple Banana Orange

Это явно проблема с IN в предложении WHERE, так как это ожидаемое поведение.

Итак, мое текущее решение состоит в том, чтобы вручную заполнить список, просматривая List и выполняя следующеекаждая строка в списке продуктов

List<Food> foodList = new ArrayList<Food>(foods.size());
    for ( String name: foods ){
        Food food = Food.find("byName", name).first();
        foodList.add(food);
    }

Это работает так, как я хочу, но просто не выглядит очень элегантно или эффективно.Дубликаты необходимы, поэтому я думаю, что исключает IN.У кого-нибудь есть идеи получше?Если ответ «нет», буду признателен за это!

Большое спасибо.

1 Ответ

0 голосов
/ 17 марта 2012

Не существует (по крайней мере, не разумного) способа построить такой запрос JPQL. Если выполнение слишком большого количества запросов в цикле беспокоит, вы можете извлечь сущности Food в одном запросе и затем сопоставить их с чем-то вроде (не скомпилированным / протестированным, а просто как идея):

List<Food> matchFoodNamesToFoods(List<String> foodNames , List<Food> foodList ) {
    final ArrayList<Food> result = new ArrayList<Food>();
    for (String foodName: foodNames) {
        for (Food food: foodList) {
            if (food.getName().equals(foodName)) {
                result.add(food);
            }
            //maybe you want to add null here when no match
        }
    }
    return result;
}

В зависимости от размера foodList и ожидаемого количества дубликатов (и, возможно, вы найдете это более понятным), вы также можете сначала создать карту с записями foodName / Food и запросить ее во внутреннем цикле:

List<Food> matchFoodNamesToFoods(List<String> foodNames , List<Food> foodList ) {
    final ArrayList<Food> result = new ArrayList<Food>();
    final Map<String, Food> foodNameToFood = new HashMap<String, Food>();
    for (Food food: foodList) {
        for (String foodName: foodNames) {
            if (food.getName().equals(foodName)) {
                foodNameToFood.put(foodName, food);
            }
        }
    }
    for (String foodName: foodNames) {
        result.add(foodNameToFood.get(foodName));
    }
    return result;
}

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

...