2017-09-25 65 views
0

在创建一些服务期间,我遇到了一些性能问题,例如: 调用服务并获取响应(对于一个对象包含RecipeComponents列表的配方 - 它花了将近2000毫秒),看起来像这样:对象其中包含一些项目列表无法公开一些查询的剩余数据

{ 
    "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 
     } 
    ] 
} 

为70+配方(含组件),以获得响应约需10000ms

的原因是服务方法,实际调用数据库的2倍(在开始我没有意识到它相当缓慢):

@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; 
在存储库层

我有两个类:RecipeRowMapper和RecipeComponentRowMapper映射数据 - 的正常工作单的查询,你可以在上面看到。

因此,我决定在存储库层中使用ResultSetExtractor,其中将使用左连接/内连接语句进行单个查询。

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

,并在这种情况下,我得到了周围1000ms的东西响应(70个食谱),但问题是反应是不完整的(不必须recipeComponents的完整名单,但名单上唯一的第一个Component):

[ 
    { 
     "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 
     } 
     ] 
    } 
] 

**我的查询工作正常。

select recipe_id,recipe_name,recipe_weight,recipe_aprox_price,recipe_raiting,recipe_calories,recipe_user_id,recipe_kcategory_id,recipe_fcategory_id,recipe_published_date,comp_id, comp_name,comp_weight,comp_description,comp_calories,comp_recipe_id from public.recipe_store INNER JOIN public.recipe_components ON (public.recipe_store.recipe_id=public.recipe_components.comp_recipe_id) 

我发现这里也有些想法切换到ORM解决这个问题,但如果你有一些想法,其他的解决方案来解决这个problms我会很感激。

回答

0

好吧,我解决了这个问题,这里是asnwer应该怎么写:

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


    } 

我希望有一天这可以帮助别人:)

相关问题