在創建一些服務期間,我遇到了一些性能問題,例如: 調用服務並獲取響應(對於一個對象包含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我會很感激。