Como receber lista de subcategorias em uma categoria

Olá pessoal,

Estou desenvolvendo um projeto pessoal para estudar e não ficar parado, visto que não consigo estágio na área. O projeto é um controle de estoque bem simples e durante o desenvolvimento tive problemas mas nada que não fosse resolvido com pesquisa até o presente momento que estou preso a um problema que não estou conseguindo entender bem como resolve-lo.

O problema é o seguinte, no sistema um produto possui uma categoria (ex: Eletrodoméstico, Informática, Livros), estes possuem uma subcategoria (ex: Televisão, Notebook, Técnico), o problema está quando preciso exibir uma lista de subcategorias para uma categoria e exibi-la na tela em um select.

Estou utilizando na aplicação o Spring e levar dados para a tela o thymeleaf.

Classe Categoria

package com.frazao.projeto.model;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.validator.constraints.NotEmpty;

@Entity
@Table(name = "tab_categoria_produto")
public class Categoria {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long codigo;

	@NotEmpty(message = "Categoria não pode ser vazia.")
	private String descricao;

	@OneToMany(mappedBy = "categoria")
	private List<Subcategoria> subcategorias;

	public Long getCodigo() {
		return codigo;
	}

	public void setCodigo(Long codigo) {
		this.codigo = codigo;
	}

	public String getDescricao() {
		return descricao;
	}

	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((codigo == null) ? 0 : codigo.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Categoria other = (Categoria) obj;
		if (codigo == null) {
			if (other.codigo != null)
				return false;
		} else if (!codigo.equals(other.codigo))
			return false;
		return true;
	}

	public List<Subcategoria> getSubcategorias() {
		return subcategorias;
	}

	public void setSubcategorias(List<Subcategoria> subcategorias) {
		this.subcategorias = subcategorias;
	}

}

Classe Subcategoria

package com.frazao.projeto.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotBlank;

@Entity
@Table(name = "subcategoria")
public class Subcategoria {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long codigo;

	@NotBlank(message = "O nome da descrição é obrigatório.")
	@Size(max = 12, message = "O número máximo de caracteres é 12.")
	private String nome;

	@NotNull(message = "Selecione uma categoria.")
	@JoinColumn(name = "cod_categoria")
	@ManyToOne
	private Categoria categoria;

	public Long getCodigo() {
		return codigo;
	}

	public void setCodigo(Long codigo) {
		this.codigo = codigo;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public Categoria getCategoria() {
		return categoria;
	}

	public void setCategoria(Categoria categoria) {
		this.categoria = categoria;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((codigo == null) ? 0 : codigo.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Subcategoria other = (Subcategoria) obj;
		if (codigo == null) {
			if (other.codigo != null)
				return false;
		} else if (!codigo.equals(other.codigo))
			return false;
		return true;
	}

}

Controller

package com.frazao.projeto.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.frazao.projeto.model.Categoria;
import com.frazao.projeto.model.Produto;
import com.frazao.projeto.model.Subcategoria;
import com.frazao.projeto.repository.Categorias;
import com.frazao.projeto.repository.SubCategorias;
import com.frazao.projeto.service.ProdutoService;

@Controller
@RequestMapping("/produtos")
public class ProdutoController {

	@Autowired
	private ProdutoService produtoService;

	@Autowired
	private Categorias categorias;

	@Autowired
	private SubCategorias subcategorias;

	// tela :: Home
	@GetMapping("/novo")
	public ModelAndView home() {
		ModelAndView mv = new ModelAndView("CadastroProduto");
		mv.addObject(new Produto());
		return mv;
	}

	// tela :: Categoria
	@GetMapping("/categoria")
	public ModelAndView categoria() {
		ModelAndView mv = new ModelAndView("Categorias");
		mv.addObject(new Categoria());
		return mv;
	}

	// tela :: Subcategoria
	@GetMapping("/categoria/subcategoria")
	public ModelAndView subcategoria() {
		ModelAndView mv = new ModelAndView("Subcategorias");
		mv.addObject(new Subcategoria());
		return mv;
	}

	// função :: Cadastrar produtos
	@PostMapping
	public String cadastrar(@Validated Produto produto, Errors errors, RedirectAttributes attributes) {
		if (errors.hasErrors()) {
			return "CadastroProduto";
		}
		produtoService.salvar(produto);
		attributes.addFlashAttribute("mensagem", "Produto cadastrado com sucesso.");
		return "redirect:/produtos/novo";
	}

	// função :: Pesquisar produtos
	@GetMapping
	public ModelAndView pesquisar() {
		ModelAndView mv = new ModelAndView("Produtos");
		return mv;
	}

	// função :: Cadastrar categorias
	@PostMapping("/novo/categoria")
	public String cadastrarCategoria(@Validated Categoria categoria, Errors errors, RedirectAttributes attributes) {
		if (errors.hasErrors()) {
			return "Categorias";
		}
		categorias.save(categoria);
		attributes.addFlashAttribute("mensagem", "Nova categoria adicionada.");
		return "redirect:/produtos/categoria";
	}

	// função :: Salvar subcategorias
	@PostMapping("/novo/categoria/subcategoria")
	public String cadastrarSubcategoria(@Validated Subcategoria subcategoria, Errors errors,
			RedirectAttributes attributes) {
		if (errors.hasErrors()) {
			return "Categorias";
		}

		subcategorias.save(subcategoria);
		attributes.addFlashAttribute("mensagem", "Subcategoria foi salva.");
		return "redirect:/produtos/categoria/subcategoria";
	}

	// função :: Entregar uma lista de categorias para a tela.
	@ModelAttribute("categorias")
	public List<Categoria> todasCategorias() {
		return categorias.findAll();
	}

}

Tela que deveria exibir a lista de subcategorias

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
	xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
	layout:decorator="LayoutPadrao">

<head>
	<title>Lista de Produtos</title>
</head>


<section layout:fragment="conteudo">
	<form class="form-horizontal" th:action="@{/produtos/novo/categoria}" method="POST" th:object="${categoria}">
		<div th:insert="~{MensagemSucesso :: mensagemSucesso}"></div>
		<div th:insert="~{MensagemErro :: mensagemErro}"></div>
		<div class="panel panel-default">
			<div class="panel-heading">
				<h3 class="panel-title">Nova Categoria</h3>
			</div>
			<div class="panel-body">

				<div class="form-group" th:classappend="${#fields.hasErrors('descricao')}? 'has-error'">
					<label for="categoria" class="col-sm-2 control-label">Categoria</label>
					<div class="col-sm-4">
						<input type="text" class="form-control" id="categoria" placeholder="Nome da nova categoria" name="descricao">
					</div>
				</div>
				<div class="form-group">
					<div class="col-sm-offset-2 col-sm-10">
						<button type="submit" class="btn btn-primary">Salvar</button>
					</div>
				</div>
			</div>
		</div>
	</form>


	<div class="panel panel-default">
			<div class="panel-heading">
				<h3 class="panel-title">Categorias</h3>
			</div>
			<div class="panel-body">
				<table class="table table-striped table-bordered">
				<thead>
					<tr>
						<td>#</td>
						<td>Categoria</td>
						<td>Subcategoria</td>
						<td></td>
					</tr>
				</thead>
				<tbody>
					<tr th:each="categoria :${categorias}">
						<td th:text="${categoria.codigo}"></td>
						<td th:text="${categoria.descricao}"></td>
						<td>
							<div class="col-sm-4">
							<select class="form-control">
								<option th:text="${categoria.subcategorias}"></option>  <--- aqui
							</select>
							</div>

							<a th:href="@{/produtos/categoria/subcategoria}"><button type="button" class="btn btn-default">+</button></a>
						</td>
						<td></td>
					</tr>
				</tbody>
			</table>
			</div>
	</div>
</section>

</html>

Da seguinte forma que estou fazendo consigo popular o select com subcategorias em suas respectivas categorias, mas somente o caminho, por exemplo Livro(categoria) - com.frazao.projeto.model.Subcategoria@20 (subcategoria). Não tenho ideia de como popular essa lista com as strings.

Se puderem me ajudar ou me passar um material de referência ficarei muito grato!

estou com esse mesmo problema, vc resolveu?