包含某些项目列表的对象无法通过单个查询公开其余数据

时间:2017-09-25 22:15:52

标签: rest spring-jdbc jdbctemplate multiple-resultsets

在创建某些服务时,我遇到了一些性能问题,例如: 调用服务并获得响应(对于一个包含RecipeComponents列表的对象Recipe - 花了近2000ms),看起来像这样:

val mEndpointDiscoveryCallback = object : EndpointDiscoveryCallback() {
        // We found someone to connect to!
        override fun onEndpointFound(endpointId: String, info: DiscoveredEndpointInfo) {
            Log.d(TAG, "onEndpointFound (we want to connect to someone!) (endpointId=$endpointId, serviceId=${info.serviceId}, endpointName=${info.endpointName})")
            if (SERVICE_ID == info.serviceId) {
                Nearby.Connections.acceptConnection(mGoogleApiClient, endpointId, mPayloadCallback)
                        .setResultCallback { status ->
                            if (!status.isSuccess) {
                                Log.w(TAG, "acceptConnection failed with ${status.toReadable()}")
                            } else {
                                Log.d(TAG, "acceptConnection success")
                                endpoints.add(endpointId)
                            }
                        }
            } else {
                Log.w(TAG, "onEndpointFound ignoring unknown endpointId=$endpointId serviceId=${info.serviceId}")
            }
        }

70多个配方(含有组件)获得响应需要大约10000毫秒

原因是服务方法,实际上调用数据库2次(在开始时我没有意识到它很慢):

{
    "recipe_id": 55,
    "recipeName": "Pizza",
    "weight": 450,
    "aproxPrice": 12,
    "raiting": 7,
    "caloriesCat": 1,
    "foodCat": 2,
    "calories": 300,
    "user_id": 500,
    "publishDate": 1505858400000,
    "recipeComponents": [
        {
            "component_id": 139,
            "componentName": "veges",
            "componentWeight": 100,
            "componentDescription": "Some desc",
            "componentCalories": 200
        },
        {
            "component_id": 140,
            "componentName": "rice",
            "componentWeight": 100,
            "componentDescription": "some stuff",
            "componentCalories": 350
        },
        {
            "component_id": 141,
            "componentName": "tomato",
            "componentWeight": 100,
            "componentDescription": "XXXXXXX",
            "componentCalories": 150
        },
        {
            "component_id": 142,
            "componentName": "souce",
            "componentWeight": 100,
            "componentDescription": "xxsdsds",
            "componentCalories": 250
        }
    ]
}

在存储库层中我有两个类:RecipeRowMapper和RecipeComponentRowMapper来映射数据 - 如上所示,它适用于单个查询。

所以我决定在存储库层中使用ResultSetExtractor,其中将使用left join / inner join语句进行单个查询。

@Override
public List<Recipe> getAllRecipes() {
    List<Recipe> recipes = recipeRepository.getAllRecipes(); <- first time to get all recipes
    for (Recipe recipe : recipes) {
        List<RecipeComponent> components = recipeComponentRepository
                .findAllComponentsAssignedToRecipe(recipe.getRecipe_id()); <- 2nd time to get components assigned to recipe.
        recipe.setRecipeComponents(components);
    }
    return recipes;

并且在这种情况下我得到响应(对于70个食谱)大约1000毫秒,但问题是响应不完整(没有完整的recipeComponents列表,但只有列表中的第一个组件):

@Override
public List<Recipe> getAllRecipesWithSingleQuery() {

    List<Recipe> recipes = jdbcTemplate.query(SqlRecipeStaticData.sGetAllRecipesWithSingleQuery,
            new ResultSetExtractor<List<Recipe>>() {

                public RecipeComponentRowMapper componentRowMapper = new RecipeComponentRowMapper();

                public RecipeRowMapper recipeRowMapper = new RecipeRowMapper();

                @Override
                public List<Recipe> extractData(ResultSet rs) throws SQLException, DataAccessException {
                    List<Recipe> recipes = new ArrayList<>();
                    Integer recipeId = null;
                    Recipe currentRecipe = null;
                    int recipeIdx = 0;
                    int componentIdx = 0;
                    while (rs.next()) {
                        if (currentRecipe == null || !recipeId.equals(rs.getInt("recipe_id"))) {
                            recipeId = rs.getInt("recipe_id");
                            currentRecipe = new Recipe();

                            currentRecipe = recipeRowMapper.mapRow(rs, recipeIdx++);
                            List<RecipeComponent> components = currentRecipe.getRecipeComponents();
                            if (components == null) {
                                components = new ArrayList<>();

                                RecipeComponent component = componentRowMapper.mapRow(rs, componentIdx++);

                                components.add(component);

                            }

                            currentRecipe.setRecipeComponents(components);
                            recipes.add(currentRecipe);

                        }

                    }
                    return recipes;
                }

            });
    return recipes;
}

**我的查询工作正常。

[  
   {  
      "recipe_id":55,
      "recipeName":"Pizza",
      "weight":450,
      "aproxPrice":12,
      "raiting":7,
      "caloriesCat":1,
      "foodCat":2,
      "calories":300,
      "user_id":500,
      "publishDate":1505858400000,
      "recipeComponents":[  
         {  
            "component_id":139,
            "componentName":"veges",
            "componentWeight":100,
            "componentDescription":"Some desc",
            "componentCalories":200
         }
      ]
   }
]

我也在这里找到一些想法切换到ORM来解决这个问题,但如果你有一些想法,其他解决这个问题的解决方案我将不胜感激。

1 个答案:

答案 0 :(得分:0)

好吧,我解决了这个问题,这里应该如何编写:

@Override
    public List<Recipe> getAllRecipesWithSingleQuery() {
        final Map<Integer,Recipe> recipesAll = new HashMap<>();
        this.jdbcTemplate.query(SqlRecipeStaticData.sGetAllRecipesWithSingleQuery, new RowMapper<RecipeComponent>(){

            @Override
            public RecipeComponent mapRow(ResultSet rs, int rowNum) throws SQLException {
                Integer recipeId = rs.getInt("r_id");
                Recipe recipe = recipesAll.get(recipeId);
                if(recipe==null){
                    recipe = new Recipe();
                    recipe.setRecipe_id(recipeId);
                    recipe.setRecipeName(rs.getString("recipe_name"));
                    recipe.setAproxPrice(rs.getDouble("recipe_aprox_price"));
                    recipe.setWeight(rs.getDouble("recipe_weight"));
                    recipe.setRaiting(rs.getInt("recipe_raiting"));
                    recipe.setCalories(rs.getDouble("recipe_calories"));
                    recipe.setUser_id(rs.getInt("ruser_id"));
                    recipe.setCaloriesCat(rs.getInt("kcategory_id"));
                    recipe.setFoodCat(rs.getInt("fcategory_id"));
                    recipe.setPublishDate(rs.getDate("published_date"));
                    recipe.setRecipeComponents(new ArrayList<>());
                    recipesAll.put(recipeId, recipe);
                }
                RecipeComponent component = new RecipeComponent();
                component.setComponent_id(rs.getInt("id"));
                component.setComponentName(rs.getString("name"));
                component.setComponentWeight(rs.getDouble("weight"));
                component.setComponentDescription(rs.getString("description"));
                component.setRecipe_id(recipeId);
                component.setComponentCalories(rs.getDouble("calories"));
                recipe.getRecipeComponents().add(component);

                return component;

            }


        });
        List<Recipe> result = new ArrayList<Recipe>(recipesAll.values());
        return result;


    }

我希望有一天这会帮助某人:)