2
respostas

[Dúvida] Problemas com a anotação @Transactional

Estava fazendo o projeto e me deparei com este erro quando executava meu código

"java.lang.NullPointerException: Cannot invoke \"med.voll.api.repositories.MedicoRepository.findAll()\" because \"this.medicoRepository\" is null\r\n\tat med.voll.api.controller.

Fui fazendo alguns testes e tentando encontrar o erro, e percebi que ele so começou quando coloquei a anotação @Transactional no meu put e post, segue o código para caso alguém saiba me ajudar

---------Controller---------

package med.voll.api.controller;

import jakarta.validation.Valid;
import med.voll.api.models.medico.DTO.AtualizarMedicoDTO;
import med.voll.api.models.medico.DTO.CreateMedicoDTO;
import med.voll.api.models.medico.DTO.ListMedicoDTO;
import med.voll.api.models.medico.Medico;
import med.voll.api.repositories.MedicoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("medicos")
public class medicoController {

    @Autowired
    private MedicoRepository medicoRepository;

    @PostMapping
    @Transactional
    private Medico create(@RequestBody @Valid CreateMedicoDTO dados){
        Medico medico = new Medico(dados);
        medicoRepository.save(medico);
        return medico;
    }

    @GetMapping
    private List<ListMedicoDTO> getAll(){
        return medicoRepository.findAll().stream().map(ListMedicoDTO::new).toList();
    }

    @PutMapping
    @Transactional
    private Medico update(@RequestBody AtualizarMedicoDTO dados){
        Medico medico = medicoRepository.getReferenceById(dados.id());
        medico.atualizarInformacoes(dados);
        medicoRepository.save(medico);
        return medico;
    }

---------Repository---------

package med.voll.api.repositories;

import med.voll.api.models.medico.Medico;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MedicoRepository extends JpaRepository<Medico, Long> {
}
2 respostas

Olá, Lucas! Como vai?

Isso ocorre porque você está utilizando a anotação @Transactional nos métodos create() e update(), mas não está configurando corretamente a injeção de dependência do MedicoRepository nesses métodos.

Uma possível solução para esse problema é mover a anotação @Transactional para a classe medicoController, logo acima da declaração da classe. Dessa forma, a transação será gerenciada para todos os métodos da classe, incluindo o create() e o update(). Ficaria assim:

@RestController
@RequestMapping("medicos")
@Transactional
public class medicoController {

    @Autowired
    private MedicoRepository medicoRepository;

    @PostMapping
    private Medico create(@RequestBody @Valid CreateMedicoDTO dados){
        Medico medico = new Medico(dados);
        medicoRepository.save(medico);
        return medico;
    }

    // Restante do código...
}

Com essa alteração, o medicoRepository será corretamente injetado nos métodos create() e update(), e o erro de NullPointerException deve ser resolvido.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.

Fiz a sugestão que vc enviou porem continua dando o mesmo erro, acho este erro muito estranho pois em outros projetos de Spring com a anotação @Transactional em cima dos métodos funciona corretamente, mas já procurei classes importadas de forma errada ou falta de alguma informação e não encontrei nada, segue o código com a anotação em cima do controller e o erro.

OBS: continuei fazendo o projeto sem a anotação @Transactional só que na atual versão que enviei ele não retorna nenhum erro em nenhum dos métodos do CRUD.

package med.voll.api.controller;

import jakarta.validation.Valid;
import med.voll.api.models.medico.DTO.AtualizarMedicoDTO;
import med.voll.api.models.medico.DTO.CreateMedicoDTO;
import med.voll.api.models.medico.DTO.ListMedicoDTO;
import med.voll.api.models.medico.Medico;
import med.voll.api.repositories.MedicoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.List;

@RestController
@RequestMapping("medicos")
@Transactional
public class medicoController {

    @Autowired
    private MedicoRepository medicoRepository;


    @GetMapping
    private ResponseEntity<Page<ListMedicoDTO>> getAll(Pageable pageable) {
        var page = medicoRepository.findAllByAtivoTrue(pageable).map(ListMedicoDTO::new);
        return ResponseEntity.ok(page);
    }

    @PostMapping
    private ResponseEntity<ListMedicoDTO> create(@RequestBody @Valid CreateMedicoDTO dados, UriComponentsBuilder uriBuilder){
        Medico medico = new Medico(dados);
        medicoRepository.save(medico);
        var uri = uriBuilder.path("/medico/{id}").buildAndExpand(medico.getId()).toUri();
        return ResponseEntity.created(uri).body(new ListMedicoDTO(medico));
    }

    @PutMapping
    private ResponseEntity<ListMedicoDTO> update(@RequestBody AtualizarMedicoDTO dados) {
        Medico medico = medicoRepository.getReferenceById(dados.id());
        medico.atualizarInformacoes(dados);
        medicoRepository.save(medico);
        return ResponseEntity.ok(new ListMedicoDTO(medico));
    }


    @DeleteMapping("/{id}")
    private ResponseEntity delete(@PathVariable Long id) {
        Medico medico = medicoRepository.getReferenceById(id);
        medico.excluir();
        medicoRepository.save(medico);
        return ResponseEntity.noContent().build();//desta forma eu retorno codigo 204
    }

}

ERRO****

java.lang.NullPointerException: Cannot invoke "med.voll.api.repositories.MedicoRepository.findAllByAtivoTrue(org.springframework.data.domain.Pageable)" because "this.medicoRepository" is null
    at med.voll.api.controller.medicoController.getAll(medicoController.java:30) ~[classes/:na]