thymeleaf не удалось преобразовать значение свойства типа java.lang.Строка в требуемый тип java.util.List

#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!"));
    }
}