在创建一些服务期间,我遇到了一些性能问题,例如:调用服务并获得响应(对于一个包含 RecipeComponents 列表的对象 Recipe - 它花费了将近 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 多个食谱(带有组件)来获得响应大约需要 10000 毫秒
原因是服务方法,实际上调用数据库 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;
}
在这种情况下,我在 1000 毫秒左右得到响应(对于 70 个食谱),但问题是响应不完整(没有完整的食谱组件列表,但只有列表中的第一个组件):
[
{
"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 来解决这个问题,但是如果你有一些想法,解决这个问题的其他解决方案我将不胜感激。