Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

[Dúvida] Unable to locate constructor for embeddable 'med.voll.api.endereco.Endereco

Eu sei que é algo relacionado ao lombok, na anotação @NoArgsConstructor , mas não sei como resolver.

minha classe Endereco:

package med.voll.api.endereco;

import jakarta.persistence.Embeddable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Embeddable
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class Endereco {

    private String logradouro;
    private String bairro;
    private String cep;
    private String numero;
    private String complemento;
    private String cidade;
    private String uf;


    public Endereco(DadosEndereco dados) {
        this.logradouro = dados.logradouro();
        this.bairro = dados.bairro();
        this.cep = dados.cep();
        this.numero = dados.numero();
        this.uf = dados.uf();
        this.cidade = dados.cidade();
        this.complemento = dados.complemento();
    }
}

Também tentei passar o atributo "force = true" na anotação @NoArgsConstructor mas o mesmo erro continuou.

Minha classe Medico:

package med.voll.api.medico;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import med.voll.api.endereco.Endereco;

@Entity(name = "Medico")
@Table(name = "medicos")
@Getter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "id")
public class Medico {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String nome;
    private String email;
    private String crm;
    @Enumerated(EnumType.STRING)
    private Especialidade especialidade;

    @Embedded
    private Endereco endereco;

    public Medico(DadosCadastroMedico dados) {
        this.nome = dados.nome();
        this.email = dados.email();
        this.crm = dados.crm();
        this.especialidade = dados.especialidade();
        this.endereco = new Endereco(dados.endereco());
    }
}

Meu plugin do lombok e a dependência dele também estão instaladas corretamente, e eu já fechei e abri o intelijj pra ver se resolvia e deu em nada. Eu não vou me estressar com isso, então só apaguei a anotação e criei o construtor vazio manualmente pra continuar com o curso, mas queria saber se alguém aqui conhece uma solução pra isso. Esse tipo de coisa sempre acontece quando tento usar o lombok, é bem chato.

1 resposta
solução!

Ola! você fez tudo quase certo, e sua análise está no caminho. Mas o erro "Unable to locate constructor for embeddable 'med.voll.api.endereco.Endereco" significa que o Hibernate (JPA) não está conseguindo encontrar um construtor sem argumentos (no-args constructor) público ou pelo menos protegido, que é obrigatório para embeddables.

E o problema aqui está no nível de acesso gerado pelo Lombok.

O que está acontecendo?

Quando você usa:

@NoArgsConstructor

O Lombok gera um construtor padrão com acesso package-private (sem modificador). O Hibernate exige que o construtor seja public ou protected, senão não consegue instanciar a classe via reflexão.

Como resolver corretamente

Você tem duas opções:

✔ Opção 1 – Tornar o construtor explícito com protected

@Embeddable
@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Endereco {
    // campos e construtor com DadosEndereco...
}

✔ Opção 2 – Escrever o construtor manualmente

Você já tentou isso, e é o mais seguro mesmo com ou sem Lombok:

public Endereco() {
    // construtor no-args necessário para o JPA
}

E o force = true?

O @NoArgsConstructor(force = true) força a criação do construtor mesmo que existam campos final, mas não altera a visibilidade, que continua sendo package-private, a menos que você especifique access = AccessLevel.PROTECTED ou PUBLIC.

Para funcionar com JPA/Hibernate, você precisa garantir que o Endereco tenha um construtor public ou protected sem argumentos. Isso é um requisito do JPA, não do Lombok.

Se quiser continuar usando o Lombok, use:

@NoArgsConstructor(access = AccessLevel.PROTECTED)

Se preferir, pode abrir mão do Lombok só nessa classe, o que é comum em projetos JPA por causa dessas particularidades.