Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Tabelas separadas

No curso a explicação foi feita para as classes Medico e Endereco foi utilizado a anotação @Embbeded no Endereco. Como eu devo proceder caso eu queira utilizar duas tabelas separadas no banco de dados? quais anotações devo, utilizar? No meu caso as duas tabelas tem id, como devo proceder?

7 respostas

Oi, Cristiano!

Entendi sua dúvida sobre como separar as entidades Medico e Endereco em duas tabelas distintas no banco de dados. Para fazer isso, você precisará usar algumas anotações diferentes do que foi mostrado no curso.

Aqui está um exemplo prático de como você pode fazer isso:

  1. Entidade Medico: Esta entidade terá uma referência à entidade Endereco usando a anotação @ManyToOne ou @OneToOne, dependendo do relacionamento que você deseja.
import jakarta.persistence.*;

@Entity
@Table(name = "medicos")
public class Medico {

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

    private String nome;

    @ManyToOne // ou @OneToOne, dependendo do seu caso
    private Endereco endereco;

    // getters e setters
}
  1. Entidade Endereco: Esta entidade será mapeada para uma tabela separada.
import jakarta.persistence.*;

@Entity
@Table(name = "enderecos")
public class Endereco {

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

    private String rua;
    private String cidade;
    private String estado;
    //outros atributos

    // getters e setters
}

Com essas anotações, o JPA/Hibernate irá criar duas tabelas separadas (medicos e enderecos) no banco de dados, e a tabela medicos terá uma coluna endereco_id que será uma chave estrangeira referenciando a tabela enderecos.

Espero ter ajudado e bons estudos!

Olá Rodrigo,tudo bem? Isso eu já tinha feito. O cenário é parecido com o do curso, o que eu tenho é uma classe beneficiario e outra de documento, mas quando eu disparo o postman recebo o seguinte erro:

"timestamp": "2024-06-20T22:19:53.411+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "trace": "org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement [Column \"DOCUMENTO_ID\" not found; SQL statement:\ninsert into beneficiarios (dataatualizacao,datainclusao,datanascimento,documento_id,nome,telefone,id) values (?,?,?,?,?,?,default) [42122-224]] [insert into beneficiarios (dataatualizacao,datainclusao,datanascimento,documento_id,nome,telefone,id) values (?,?,?,?,?,?,default)]; SQL [insert into beneficiarios (dataatualizacao,datainclusao,datanascimento,documento_id,nome,telefone,id) values (?,?,?,?,?,?,default)

Só que eu não tenho essa coluna DOCUMENTO_ID. A estrutura das tabelas é a seguinte:

create table documento(

    id bigint auto_increment,
    tipodocumento varchar(100),
    descricao varchar(100),
    datainclusao varchar(100),
    dataatualizacao varchar(100),

    primary key(id)

);
create table beneficiarios(

    id bigint auto_increment,
    nome varchar(100),
    telefone varchar(100),
    datanascimento varchar(100),
    datainclusao varchar(100),
    dataatualizacao varchar(100),

    primary key(id)

);

As classes do projeto são:

package com.ekan.api.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.ekan.api.beneficiario.Beneficiario;
import com.ekan.api.beneficiario.BeneficiarioRepository;
import com.ekan.api.beneficiario.DadosCadastroBeneficiario;

@RestController
@RequestMapping("/beneficiarios")
public class BeneficiarioController {
    
    @Autowired
    private BeneficiarioRepository repository;
    
    @PostMapping
    @Transactional
    public void cadastrar(@RequestBody DadosCadastroBeneficiario dados) {
        repository.save(new Beneficiario(dados));
        
    }

}
package com.ekan.api.beneficiario;

import jakarta.persistence.ElementCollection;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

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

    public Beneficiario(DadosCadastroBeneficiario dados) {
        this.nome = dados.nome();
        this.telefone = dados.telefone();
        this.datanascimento = dados.datanascimento();
        this.datainclusao = dados.datainclusao();
        this.dataatualizacao = dados.dataatualizacao();
        this.documento = new Documento(dados.documento());
    }

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String nome;
    private String telefone;
    private String datanascimento;
    private String datainclusao;
    private String dataatualizacao;
    
    @ManyToOne
    private Documento documento;
    ```
    
    ``
    package com.ekan.api.beneficiario;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Table(name= "documentos")
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "id")
public class Documento {
    public Documento(DadosDocumentos dados) {
        this.tipoDocumento = dados.tipoDocumento();
        this.descricao = dados.descricao();
        this.dataInclusao = dados.dataInclusao();
        this.dataAtualizacao = dados.dataAtualizacao();
    }
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String tipoDocumento;
    private String descricao;
    private String dataInclusao;
    private String dataAtualizacao;
    
}
package com.ekan.api.beneficiario;

public record DadosDocumentos(String tipoDocumento, String descricao, String dataInclusao, String dataAtualizacao) {

}
package com.ekan.api.beneficiario;

public record DadosCadastroBeneficiario(String nome, String telefone, String datanascimento, String datainclusao, String dataatualizacao, DadosDocumentos documento) {

}
{
"nome": "Rodrigo Ferreira",
"telefone": "2325245",
"dataNascimento": "123456",
"dataInclusao": "23011975",
"dataAtualizacao": "23011975",
"documento": {
    "tipoDocumento": "rua 1",
    "decricao": "bairro",
    "dataInclusao": "12345678",
    "dataAtualizacao": "Brasilia"
    }
}

O relacionamento entre as tabelas é Beneficiario 1 ----------------- * Documento Alguma dica? Obrigado desde já

Se no seu caso o relacionamento é um para muitos de benefiário para documento, ou seja, um beneficiário pode ter vários documentos, mas um documento pertence a apenas um beneficiário, então é na tabela documentos que que precisa ter a chave estrangeira para a tabela de beneficiarios.

alter table documentos add beneficiario_id bigint;
@Table(name= "documentos")
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "id")
public class Documento {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String tipoDocumento;
    private String descricao;
    private String dataInclusao;
    private String dataAtualizacao;
    
    @ManyToOne
    private Beneficiario beneficiario;
    
}

Olá Rodrigo. Obrigado pela ajuda. Mas estou recebendo esse erro quando eu disparo o postman, eplo que eu andei pesquisando na internet acho que a minha aplicação está tentando salvar os documentos antes do beneficiario. Estou errado? Como resolver?

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.ekan.api.beneficiario.Beneficiario.documentos -> com.ekan.api.beneficiario.Documentos\

@Table(name = "beneficiarios")
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "id")
public class Beneficiario {

    public Beneficiario(DadosCadastroBeneficiario dados) {
        this.nome = dados.nome();
        this.telefone = dados.telefone();
        this.datanascimento = dados.datanascimento();
        this.datainclusao = dados.datainclusao();
        this.dataatualizacao = dados.dataatualizacao();
        this.documentos = new Documentos(dados.documentos());
    }

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String nome;
    private String telefone;
    private String datanascimento;
    private String datainclusao;
    private String dataatualizacao;
    
    @ManyToOne
    private Documentos documentos;
    

}

@Table(name= "documentos")
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(of = "id")
public class Documentos {
    public Documentos(DadosDocumentos documentos) {
        this.tipoDocumento = documentos.tipoDocumento();
        this.descricao = documentos.descricao();
        this.dataInclusao = documentos.dataInclusao();
        this.dataAtualizacao = documentos.dataAtualizacao();
    //	this.beneficiario = new Beneficiario(dados.beneficiario());

    }
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String tipoDocumento;
    private String descricao;
    private String dataInclusao;
    private String dataAtualizacao;
    
    @ManyToOne
    private Beneficiario beneficiario;
    
}
 BENEFICIARIOS
 ID
 NOME
 TELEFONE
 DATANASCIMENTO
 DATAINCLUSAO
 DATAATUALIZACAO
 DOCUMENTOS_ID
 
 DOCUMENTOS
 ID
 TIPODOCUMENTO
 DESCRICAO
 DATAINCLUSAO
 DATAATUALIZACAO
 BENEFICIARIO_ID
 
solução!

consegui resolver com o @ManyToOne(cascade = CascadeType.PERSIST)

Obrigado professor