Criei um projetinho utilizando o JPA mais Spring, com as entidades Categoria, Curso, Disciplina, onde uma Categoria terá vários Cursos e um Curso irá pertencer a apenas uma Categoria, o Curso terá 0 ou N Disciplinas e a Disciplina pode pertencer a 0 ou N Cursos. Fiz as entidades, repositórios e services e está funcionando o create, update e delete, porém quando tento realizar alguma busca, seja por todos os elementos de uma entidade ou pelo Id o corre o erro: java.lang.StackOverflowError: null
Imagino que seja pq uma entidade está chamando a outra de forma recursiva e infinita e estoura a exception, mas não faço ideia de como arrumar, se alguem puder me ajudar ficarei muito agradecido.
Entidade Categoria:
@Entity
@Table(name = "categorias")
public class Categoria {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String nomeCategoria;
private String descricao;
@OneToMany(mappedBy = "categoria", fetch = FetchType.EAGER)
private List<Curso> cursos;
@Deprecated
public Categoria(){}
public Categoria(String nomeCategoria, String descricao) {
this.nomeCategoria = nomeCategoria;
this.descricao = descricao;
}
public Long getId() {
return id;
}
public String getNomeCategoria() {
return nomeCategoria;
}
public void setNomeCategoria(String nomeCategoria) {
this.nomeCategoria = nomeCategoria;
}
public String getDescricao() {
return descricao;
}
public void setDescricao(String descricao) {
this.descricao = descricao;
}
public List<Curso> getCursos() {
return cursos;
}
public void setCursos(List<Curso> cursos) {
this.cursos = cursos;
}
@Override
public String toString() {
return "Categoria{" +
"id=" + id +
", nomeCategoria='" + nomeCategoria + '\'' +
", descricao='" + descricao + '\'' +
", cursos=" + cursos +
'}';
}
}
Entidade Curso:
@Entity
@Table(name = "cursos")
public class Curso {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String nomeCurso;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "categoria_id", nullable = false)
@JsonIgnore
private Categoria categoria;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "cursos_disciplinas", joinColumns = @JoinColumn(name = "curso_fk"),
inverseJoinColumns = @JoinColumn(name = "disciplina_fk")
)
private List<Disciplina> disciplinas;
@Deprecated
public Curso(){}
public Curso(String nomeCurso, Categoria categoria) {
this.nomeCurso = nomeCurso;
this.categoria = categoria;
}
public Long getId() {
return id;
}
public String getNomeCurso() {
return nomeCurso;
}
public void setNomeCurso(String nomeCurso) {
this.nomeCurso = nomeCurso;
}
public Categoria getCategoria() {
return categoria;
}
public void setCategoria(Categoria categoria) {
this.categoria = categoria;
}
public List<Disciplina> getDisciplinas() {
return disciplinas;
}
public void setDisciplinas(List<Disciplina> disciplinas) {
this.disciplinas = disciplinas;
}
@Override
public String toString() {
return "Curso{" +
"id=" + id +
", nomeCurso='" + nomeCurso + '\'' +
", categoria=" + categoria +
", disciplinas=" + disciplinas +
'}';
}
}
Entidade Disciplina:
@Entity
@Table(name = "disciplinas")
public class Disciplina {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String nomeDisciplina;
private TipoAula tipoAula;
@Column(nullable = false)
private Double cargaHoraria;
@ManyToMany(mappedBy = "disciplinas", fetch = FetchType.LAZY)
@JsonIgnore
private List<Curso> cursos;
@Deprecated
public Disciplina(){}
public Disciplina(String nomeDisciplina, TipoAula tipoAula, Double cargaHoraria) {
this.nomeDisciplina = nomeDisciplina;
this.tipoAula = tipoAula;
this.cargaHoraria = cargaHoraria;
}
public Long getId() {
return id;
}
public String getNomeDisciplina() {
return nomeDisciplina;
}
public void setNomeDisciplina(String nomeDisciplina) {
this.nomeDisciplina = nomeDisciplina;
}
public TipoAula getTipoAula() {
return tipoAula;
}
public void setTipoAula(TipoAula tipoAula) {
this.tipoAula = tipoAula;
}
public Double getCargaHoraria() {
return cargaHoraria;
}
public void setCargaHoraria(Double cargaHoraria) {
this.cargaHoraria = cargaHoraria;
}
public List<Curso> getCursos() {
return cursos;
}
public void setCursos(List<Curso> cursos) {
this.cursos = cursos;
}
@Override
public String toString() {
return "Disciplina{" +
"id=" + id +
", nomeDisciplina='" + nomeDisciplina + '\'' +
", tipoAula=" + tipoAula +
", cargaHoraria=" + cargaHoraria +
", cursos=" + cursos +
'}';
}
}
Não irei colocar o código dos repositorys mas estão herdando de CrudRepository
Categoria Service:
@Service
public class CategoriaService {
private CategoriaRepository categoriaRepository;
public CategoriaService(CategoriaRepository categoriaRepository){
this.categoriaRepository = categoriaRepository;
}
public void visualizar(){
Iterable<Categoria> categorias = categoriaRepository.findAll();
System.out.println(categorias);
}
public void visualizarPorIdConsole(Long id){
Optional<Categoria> cateogoriaPorId = categoriaRepository.findById(id);
if(cateogoriaPorId.isPresent())
System.out.println(cateogoriaPorId.get());
else
System.out.println("Categoria procurada pelo Id: " + id + " Não foi encontrada");
}
public Categoria visualizarPorId(Long id){
Optional<Categoria> cateogoriaPorId = categoriaRepository.findById(id);
if(cateogoriaPorId.isPresent())
return cateogoriaPorId.get();
else
return null;
}
public Categoria cadastrar(String nome, String descricao){
Categoria categoria = new Categoria(nome, descricao);
this.categoriaRepository.save(categoria);
return categoria;
}
public void atualizar(Long id, String nome, String descricao){
Optional<Categoria> categoriaById = this.categoriaRepository.findById(id);
if(categoriaById.isPresent()){
Categoria categoria = categoriaById.get();
categoria.setNomeCategoria(nome);
categoria.setDescricao(descricao);
this.categoriaRepository.save(categoria);
}
}
public void deletar(Long id){
this.categoriaRepository.deleteById(id);
}
}
Curso Service:
@Service
public class CursoService {
private CursoRepository cursoRepository;
private DisciplinaRepository disciplinaRepository;
public CursoService(CursoRepository cursoRepository, DisciplinaRepository disciplinaRepository){
this.cursoRepository = cursoRepository;
this.disciplinaRepository = disciplinaRepository;
}
public void visualizar(){
Iterable<Curso> cursos = cursoRepository.findAll();
System.out.println(cursos.toString());
}
public void visualizarPorIdTerminal(Long id){
Optional<Curso> cursoPorId = cursoRepository.findById(id);
if(cursoPorId.isPresent())
System.out.println(cursoPorId.get());
else
System.out.println(("Não Encontrado o Curso pelo Id: " + id));
}
public Curso visualizarPorId(Long id){
Optional<Curso> cursoPorId = cursoRepository.findById(id);
if(cursoPorId.isPresent()){
Curso curso = cursoPorId.get();
return curso;
}
else
return null;
}
public void cadastrar(String nomeCurso, Categoria categoria){
Curso curso = new Curso(nomeCurso, categoria);
cursoRepository.save(curso);
}
public void atualizar(Long id, String nomeCurso, Categoria categoria){
Optional<Curso> cursoPorId = cursoRepository.findById(id);
if(cursoPorId.isPresent()){
Curso curso = cursoPorId.get();
curso.setNomeCurso(nomeCurso);
curso.setCategoria(categoria);
cursoRepository.save(curso);
}
else
System.out.println("O Curso procurado pelo Id: " + id + "Não foi encontrado");
}
public void deletar(Long id){
cursoRepository.deleteById(id);
}
private List<Disciplina> sicronizarDisciplinas(List<Long> ids){
List<Disciplina> disciplinas = new ArrayList<>();;
for(var x = 0; x < ids.size(); x++){
Optional<Disciplina> disciplinaPorId = disciplinaRepository.findById(ids.get(x));
if(disciplinaPorId.isPresent()){
Disciplina disciplina = disciplinaPorId.get();
disciplinas.add(disciplina);
}
else
return null;
}
return disciplinas;
}
public void cadastrarDisciplinasNoCurso(Long idCurso, List<Long> idDisciplina){
Optional<Curso> cursoPorId = cursoRepository.findById(idCurso);
if(cursoPorId.isPresent()){
Curso curso = cursoPorId.get();
List<Disciplina> disciplinas = this.sicronizarDisciplinas(idDisciplina);
curso.getDisciplinas().addAll(disciplinas);
this.cursoRepository.save(curso);
}
}
}
Disciplina Service:
@Service
public class DisciplinaService {
private DisciplinaRepository disciplinaRepository;
public DisciplinaService(DisciplinaRepository disciplinaRepository) {
this.disciplinaRepository = disciplinaRepository;
}
public void visualizar(){
Iterable<Disciplina> disciplinas = disciplinaRepository.findAll();
System.out.println(disciplinas);
}
public void visualizarPorId(Long id){
Optional<Disciplina> disciplinaPorId = disciplinaRepository.findById(id);
if(disciplinaPorId.isPresent()){
Disciplina disciplina = disciplinaPorId.get();
System.out.println(disciplina);
}
else
System.out.println("Disciplina procurada pelo Id: " + id + "Não foi encontrada");
}
public void cadastrar(String nomeDisciplina, TipoAula tipoAula, Double cargaHoraria){
Disciplina disciplina = new Disciplina(nomeDisciplina, tipoAula, cargaHoraria);
disciplinaRepository.save(disciplina);
}
public void atualizar(Long id, String nomeDisciplina, TipoAula tipoAula, Double cargaHoraria){
Optional<Disciplina> disciplinaPorId = disciplinaRepository.findById(id);
if(disciplinaPorId.isPresent()){
Disciplina disciplina = disciplinaPorId.get();
disciplina.setNomeDisciplina(nomeDisciplina);
disciplina.setTipoAula(tipoAula);
disciplina.setCargaHoraria(cargaHoraria);
disciplinaRepository.save(disciplina);
}
else
System.out.println("Disciplina buscada pelo Id: " + id + "Não foi encontrada");
}
public void deletar(Long id){
disciplinaRepository.deleteById(id);
}
}