Home > Mobile >  get API in spring boot with one to many relation
get API in spring boot with one to many relation

Time:06-26

I have two models that are having one to many relation (customers have many invoices) so i create one - many relation on it, this is my customer class :

@Entity
@Table(name = "customer")
public class Customer {
    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private int id;
    @Column(name = "serial_number")
    private long serialNumber;
    @Column(name = "first_name")
    private String firstName;
    @Column(name = "last_name")
    private String lastName;
    @Column(name = "email")
    private String email;
    @Column(name = "mobile_number")
    private String mobileNumber;
    @Column(name = "is_deleted")
    private boolean isDeleted;


    @OneToMany
    private Set <Invoice> invoices;
}

and this is invoices class :

@Entity
@Table(name = "invoice")
public class Invoice {

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private int id;
    @Column(name = "serial_number")
    private long serialNumber;
    @Column(name = "status")
    private String status;
    @Column(name = "created_date")
    private Timestamp createdDate;
    @Column(name = "is_deleted")
    private boolean isDeleted;
    @ManyToOne
    @JoinColumn(name = "customer_id")
    private Customer customer;
}

and then i create GET API ( get customers ) but it's nor working and return this error :

nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not extract ResultSet (through reference chain: java.util.ArrayList[0]->com.example.invoices.model.Customer["invoices"]), path=/customer/viewList}]

and this is my api :

public List<Customer> getAllCustomers() {
    List<Customer> customers =  cutomerRepository.findAll();
    return customers;
}

and controller :

   @GetMapping("/viewList")
    public ResponseEntity<List<Customer>> getAllCustomers() {
            List<Customer> customers = new ArrayList<>();
            customers = customerService.getAllCustomers();
            if (customers.isEmpty()) {
                return new ResponseEntity<>(HttpStatus.NO_CONTENT);
            }
            return new ResponseEntity<>(customers, HttpStatus.OK);
    }

CodePudding user response:

Do not open the entity class directly to the outside world

DTO use

for example

public class InvoiceDTO {

private int id;

private long serialNumber;

private String status;

private Timestamp createdDate;

private boolean isDeleted;

private CustomerDTO customer;

}

Apply see here:

https://github.com/musanabiyev/FurnitureStoreApplication/tree/main/src/main/java/com/company/dto

CodePudding user response:

You have a Bidirectional relation and therefore an endless loop if json tries to deserialize the Object.

You can use @JsonIgnore to break the loop or use DTOs to return at the endpoint

@Entity
@Table(name = "invoice")
public class Invoice {

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private int id;
    @Column(name = "serial_number")
    private long serialNumber;
    @Column(name = "status")
    private String status;
    @Column(name = "created_date")
    private Timestamp createdDate;
    @Column(name = "is_deleted")
    private boolean isDeleted;
    @ManyToOne
    @JsonIgnore
    @JoinColumn(name = "customer_id")
    private Customer customer;
}

DTO would look something like this (I like to use records for this but since I don't know if you use Java 17 I still use class):

Customer:

@Data
public class CustomerDTO {
    private int id;
    private long serialNumber;
    private String firstName;
    private String lastName;
    private String email;
    private String mobileNumber;
    private boolean isDeleted;

    private Set <Invoice> invoices;
}

Invoice (here you don't show the customer again):

@Data
public class InvoiceDTO {
    private int id;
    private String status;
    private Timestamp createdDate;
    private boolean isDeleted;
}
  • Related