#spring-boot #thymeleaf
#spring-boot #thymeleaf
Вопрос:
Я новичок в Spring и Spring Boot и работаю над книгой, в которой полно недостающей информации.
У меня есть класс taco:
public class Taco {
...
@Size(min=1, message="You must choose at least 1 ingredient")
private List<Ingredient> ingredients;
...
}
Как вы можете видеть, ingredients
имеет тип List<Ingredient>
, и в этом проблема, раньше оно было типа List<String>
, но это было до того, как я начал сохранять данные в базе данных, теперь оно должно быть List<Ingredient>
, что нарушает все это.
В компоненте у меня есть следующее (среди прочего, я думаю, что это единственный требуемый код для рассматриваемой проблемы, но если вам нужно больше, дайте мне знать):
@ModelAttribute
public void addIngredientsToModel(Model model) {
List<Ingredient> ingredients = new ArrayList<>();
ingredientRepo.findAll().forEach(i -> ingredients.add(i));
Type[] types = Ingredient.Type.values();
for (Type type : types) {
model.addAttribute(type.toString().toLowerCase(), filterByType(ingredients, type));
}
}
private List<Ingredient> filterByType(List<Ingredient> ingredients, Type type) {
return ingredients
.stream()
.filter(x -> x.getType()
.equals(type))
.collect(Collectors.toList());
}
И, наконец, в моем файле thymeleaf у меня есть:
<span class="text-danger"
th:if="${#fields.hasErrors('ingredients')}"
th:errors="*{ingredients}">
</span>
Что вызывает ошибку:
thymeleaf Failed to convert property value of type java.lang.String to required type java.util.List
Еще раз, когда это private List<Ingredient> ingredients;
было private List<String> ingredients;
, это работало, но теперь это должно быть private List<Ingredient> ingredients;
из-за способа сохранения в базе данных, но на этом этапе происходит сбой, как это исправить?
Комментарии:
1. Вы должны определить th: object в своей форме, чтобы Thymeleaf мог распознать ваш объект Ingredients.
2. У меня была похожая ошибка. Код, полученный из книги, может содержать ошибки.
Ответ №1:
Я столкнулся с той же проблемой, здесь нам нужен конвертер.
package tacos.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import tacos.Ingredient;
import tacos.data.IngredientRepository;
@Component
public class IngredientByIdConverter implements Converter<String, Ingredient> {
private IngredientRepository ingredientRepo;
@Autowired
public IngredientByIdConverter(IngredientRepository ingredientRepo) {
this.ingredientRepo = ingredientRepo;
}
@Override
public Ingredient convert(String id) {
return ingredientRepo.findOne(id);
}
}
Комментарии:
1. Как это должно вызываться при выполнении привязки?
Ответ №2:
Оптимизация ответа Яна выше:
Извлеките ингредиенты в конструкторе конвертера.
package com.joeseff.xlabs.chtp01_1.tacos.converter;
import com.joeseff.xlabs.chtp01_1.tacos.model.Ingredient;
import com.joeseff.xlabs.chtp01_1.tacos.respository.jdbc.IngredientRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* @author - JoeSeff
* @created - 23/09/2020 13:41
*/
@Component
public class IngredientConverter implements Converter<String, Ingredient> {
private final IngredientRepository ingredientRepo;
private final List<Ingredient> ingredients = new ArrayList<>();
@Autowired
public IngredientConverter(IngredientRepository ingredientRepo) {
this.ingredientRepo = ingredientRepo;
ingredientRepo.findAll().forEach(ingredients::add);
}
@Override
public Ingredient convert(String ingredientId) {
return ingredients
.stream().filter( i -> i.getId().equals(ingredientId))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Ingredient with ID '" ingredientId "' not found!"));
}
}