1

I'm new to this tool and I'm having trouble with this specific issue. I looked for an example But could not find something similar, better, I found a possible solution, but in my case It doesn't work.

I have this narrow project that resembles our famous CRUD, and I'm trying to reference the primary key from one table to another.

  1. Client Entity:

    @Entity
    @Table(name = "client")             
    public class Client {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(name = "cpf", length = 14)
        private String cpf;
    
        @Column(name = "name", length = 100)
        private String name;
    
        @Column(name = "birth_date")
        private LocalDate birthDate;
    
        @Column(name = "address", length = 255)
        private String address;
    
        @Column(name = "telephone", length = 14)
        private String telephone;
    
        @Column(name = "email", length = 200)
        private String email;
    
        @Column(name = "date_register", insertable = true, updatable = false)
        private LocalDate dateRegister;
    
        public Client() {
            super();
        }
    
        public Client(Long id, String cpf, String name, LocalDate birthDate, String address, String telephone, String email, LocalDate dateRegister) {
            super();
            this.id = id;
            this.cpf = cpf;
            this.name = name;
            this.birthDate = birthDate;
            this.address = address;
            this.telephone = telephone;
            this.email = email;
            this.dateRegister = dateRegister;
        }
    
        public Client(String cpf, String name, LocalDate birthDate, String address, String telephone, String email, LocalDate dateRegister) {
            super();
            this.cpf = cpf;
            this.name = name;
            this.birthDate = birthDate;
            this.address = address;
            this.telephone = telephone;
            this.email = email;
            this.dateRegister = dateRegister;
        }
    
        @PrePersist
        public void prePersist() {
            setDateRegister(LocalDate.now());
        }
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getCpf() {
            return cpf;
        }
    
        public void setCpf(String cpf) {
            this.cpf = cpf;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public LocalDate getBirthDate() {
            return birthDate;
        }
    
        public void setBirthDate(LocalDate birthDate) {
            this.birthDate = birthDate;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getTelephone() {
            return telephone;
        }
    
        public void setTelephone(String telephone) {
            this.telephone = telephone;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public LocalDate getDateRegister() {
            return dateRegister;
        }
    
        public void setDateRegister(LocalDate dateRegister) {
            this.dateRegister = dateRegister;
        }
    
        @Override
        public String toString() {
            return "Client [id=" + id + ", cpf=" + cpf + ", name=" + name + ", birthDate=" + birthDate + ", address="
            + address + ", telephone=" + telephone + ", email=" + email + ", dateRegister=" + dateRegister + "]";
        }
    }
    
  2. Sale Entity:

    @Entity
    @Table(name = "sale")
    public class Sale {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @ManyToOne
        @JoinColumn(name = "client_id")
        private Client client;
    
        @OneToMany(mappedBy = "sale")
        private List<SaleItem> items;
    
        @Column(name = "payment_type", length = 10)
        @Enumerated(EnumType.STRING)
        private PaymentType paymentType;
    
        @Column(name = "amount")
        private BigDecimal amount;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public Client getClient() {
            return client;
        }
    
        public void setClient(Client client) {
            this.client = client;
        }
    
        public List<SaleItem> getItems() {
            return items;
        }
    
        public void setItems(List<SaleItem> items) {
            this.items = items;
        }
    
        public PaymentType getPaymentType() {
            return paymentType;
        }
    
        public void setPaymentType(PaymentType paymentType) {
            this.paymentType = paymentType;
        }
    
        public BigDecimal getAmount() {
            return amount;
        }
    
        public void setAmount(BigDecimal amount) {
            this.amount = amount;
        }
    
        @Override
        public String toString() {
            return "Sale [id=" + id + ", client=" + client + ", items=" + items + ", paymentType=" + paymentType
            + ", amount=" + amount + "]";
        }   
    }
    

The objective is to link the client to a sale through its primary key. These two codes refer to the sales repository and its controller:

  1. SaleRepository:

    public interface SaleRepository extends JpaRepository<Sale, Long> {
    
    }
    
  2. SaleController:

     @RestController
     @RequestMapping("/api/sales")
     @CrossOrigin("*")
     public class SaleController {
    
         @Autowired
         private SaleRepository repository;
    
         @Autowired
         private SaleItemRepository saleItemrepository;
    
         @PostMapping
         @Transactional
         public void save(@RequestBody Sale sale) {
             repository.save(sale);
             sale.getItems().stream().forEach(saleItem -> saleItem.setSale(sale));
             saleItemrepository.saveAll(sale.getItems());
         }
    
    }
    

And the problem is exactly how this reference is being made. In the current private Client client; way , the client object is being passed in full instead of its id, that's why it throws this following error when I try to register the sale.

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.time.LocalDate` from String "31/05/1968": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '31/05/1968' could not be parsed at index 0; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDate` from String "31/05/1968": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '31/05/1968' could not be parsed at index 0<EOL> at [Source: (PushbackInputStream); line: 1, column: 87] (through reference chain: MyNameIsRafaelSampaio.github.com.bruxo_vendas_ltda_api.model.Sale["client"]->MyNameIsRafaelSampaio.github.com.bruxo_vendas_ltda_api.model.Client["birthDate"])]

As was to be expected, since the column birthDate present in the client entity is not being treated correctly in the sale entity. I did research on a possible solution but none made much sense to me, I believe for being a newbie, one of the solutions that I found more understandable was the use of the @MapsId tag. I tried to make changes to adapt, but I was not successful, if you can help I will be grateful.

Martin Lippert
  • 5,988
  • 1
  • 15
  • 18
rafalindo
  • 13
  • 5

0 Answers0