简体   繁体   中英

Java Play Framework using Find and JPQL to create an object list with duplicates from string list

So I am new to Java and Play still get confused from time to time about quasi object oriented programming...

I need to convert a delimited string with duplicate values into an Object list, also with those duplicate values, in the same order as the string.

Example:

I have a form where a user submits of space delimited string. For example:

http://www.feedme.com?food=apple+orange+banana+apple+grape+apple

that goes to

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;
}

I print the loop of the String list to the screen and get the expected: apple orange banana apple grape apple

I print the Food.name value for each in the loop of the foodList and get: Grape Apple Banana Orange

This is clearly an issue with IN in the WHERE clause, as that's the expected behavior.

So, my current solution is to manually populate the List by looping through List and running the following on each String in the List foods

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

This works how I want it but just doesn't seem very elegant or efficient. The duplicates ARE required, so I think that rules out IN. Does anyone have any better ideas? If the answer is no, would appreciate that too!

Many thanks.

There is no (at least not reasonable) way to construct such a JPQL query. If executing too many queries in loop bothers, you can fetch Food entities in one query and map them afterwards with something like (not compiled/tested, but just as an idea):

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;
}

Depending about size of of foodList and expected amount of duplicates (and maybe you find it more clear as well) you can also first create map with foodName/Food entries and query it in inner loop:

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;
}

Additionally you have to decide does missing Food for some name produce null entry to the result or is such a anomaly that you rather through exception in such a case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM