Não consigo mostrar uma exceção quando coloco um valor que minha chave estrangeira não existe em JSON quando vou persistir

Possuo uma classe Lancamento que dentro dela tenho 2 chaves estrangeiras que seria pessoa_codigo e categoria_codigo , consegui criar uma exceção quando informo um valor inexistente para alguma dessas chaves estrangeira! Neste caso, só estou conseguindo capturar o erro em uma coluna que seria: categoria_codigo já a coluna pessoa_codigo * não consigo, pois me traz uma exceção que não sei como resolver.

Exemplo do meu JSON ao tentar persistir o objeto lancamento

   { "descricao": "Lanche",
"dataVencimento": "2017-06-10",
"dataPagamento": null,
"valor": 10.20,
"observacao": null,
"tipoLancamento": "DESPESA",
"categoria": {
    "codigo": 100
},
"pessoa": {
    "codigo": 10
    }
}

Repare que no codigo da categoria eu coloquei o 100 que no caso não existe essa categoria no banco, mas consegui capturar minha exceção:

 {
"msgUsuario": "Operação não permitida",
"msgDesenvolvedor": "SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`algamoneyapi`.`lancamento`, CONSTRAINT `lancamento_ibfk_1` FOREIGN KEY (`codigo_categoria`) REFERENCES `categoria` (`codigo`))"

}

Agora vou colocar por exemplo um valor no código na pessoa que não existe. e tenho esse Erro:

"timestamp": "2021-04-27T00:16:31.897+00:00",
"status": 500,
"error": "Internal Server Error",
"trace": "java.util.NoSuchElementException: No value present\n\tat java.base/java.util.Optional.get(Optional.java:141)\n\tat com.example.algamoney.service.LancamentoService.salva(LancamentoService.java:27)\n\tat com.example.algamoney.resource.LancamentoResource.criar(LancamentoResource.java:63)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)\n\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.base/java.lang.reflect.Method.invoke(Method.java:564)\n\tat org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle
  "message": "No value present",
"path": "/lancamentos"

Minha classe Service

@Service
public class LancamentoService {

    @Autowired
    private PessoaRepository pessoaRepository;

    @Autowired
    private LancamentoRepository lancamentoRepository;

    public Lancamento salva(Lancamento lancamento) {

        Optional<Pessoa> pessoaRecuperada = pessoaRepository.findById(lancamento.getPessoa().getCodigo());
        if (pessoaRecuperada == null || pessoaRecuperada.get().isAtivo() == false) {
            
            throw new PessoaInexistenteOuInativaException();
        }
        return lancamentoRepository.save(lancamento);
    }

Você precisa de um ExceptionHandler para tratar a sua exceção customizada!

Para a categoria o tratamento ocorre normalmente porquê provavelmente você já tem um ExceptionHandler do tipo ControllerAdvice que resolve a exceção SQLIntegrityConstraintViolationException, já para a exceção PessoaInexistenteOuInativaException acredito que não tenha, por isso o erro 500 é retornado ao invés de uma mensagem tratada.

Exemplo:

    @ExceptionHandler(PessoaInexistenteOuInativaException.class)
    public ResponseEntity<Object> handlePessoaInexistenteOuInativaException(PessoaInexistenteOuInativaException ex) {
        // Tratativa de mensagem de resposta
        // "erros" dentro de body simboliza por exemplo uma lista de erros a ser retornada, ou até mesmo um objeto simples
        return ResponseEntity.badRequest().body(erros);
    }