I'm building a RESTful API GET method with Spring Boot to get return of a Bill entity as JSON from database. The return is not expected as it has many duplicated values and a StackOverFlowError.
[{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":{"id":1,"date":"2022-05-20","time":"16:48:06","total":330000.0,"billDetails":[{"billMenuItemID":{"billId":1,"menuItemId":1},"bill":
//continues for eternity
Hibernate log:
Hibernate:
select
bill0_.bill_id as bill_id1_0_,
bill0_.date as date2_0_,
bill0_.time as time3_0_,
bill0_.total as total4_0_
from
bill bill0_
Hibernate:
select
billdetail0_.bill_id as bill_id1_1_0_,
billdetail0_.menu_item_id as menu_ite2_1_0_,
billdetail0_.bill_id as bill_id1_1_1_,
billdetail0_.menu_item_id as menu_ite2_1_1_,
billdetail0_.quantity as quantity3_1_1_,
billdetail0_.subtotal as subtotal4_1_1_,
menuitem1_.menu_item_id as menu_ite1_2_2_,
menuitem1_.description as descript2_2_2_,
menuitem1_.img_url as img_url3_2_2_,
menuitem1_.name as name4_2_2_,
menuitem1_.price as price5_2_2_,
menuitem1_.status as status6_2_2_,
menuitem1_.type as type7_2_2_
from
bill_detail billdetail0_
inner join
menu_item menuitem1_
on billdetail0_.menu_item_id=menuitem1_.menu_item_id
where
billdetail0_.bill_id=?
How can I get a return of a Bill like this:
{
"billId": 1,
"date": 2022-05-20,
"time": 16:48:06,
"total": 330000,
"billDetails": [
{
"menuItem": {
"id": 1,
"name": Rice,
// other attributes of MenuItem
},
"quantity": 2
"subtotal": 90000
},
{
"menuItem": {
"id": 2
"name": Wine
// other attributes of MenuItem
},
"quantity": 4
"subtotal": 240000
}
]
}
This is my classes and related functions
Class Bill
@Entity(name = "bill")
@Table(name = "bill")
public class Bill {
@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
@Column(name = "bill_id")
private Long id;
private LocalDate date;
private LocalTime time;
private Double total;
@OneToMany(mappedBy = "bill", cascade = CascadeType.ALL)
private List<BillDetail> billDetails = new ArrayList<>();
Class MenuItem
@Entity
@Table(name = "menuItem",
uniqueConstraints = {
@UniqueConstraint(name = "menu_item_name_unique", columnNames = "name")
}
)
public class MenuItem {
@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
@Column(name = "menu_item_id")
private Long id;
private ItemType type;
private String name;
private String description;
private String imgUrl;
private Double price;
private MenuItemStatus status = MenuItemStatus.ENABLED;
@OneToMany(mappedBy = "menuItem", cascade = CascadeType.ALL)
private List<BillDetail> billDetails = new ArrayList<>();
Class BillDetail
@Entity
@Table(name = "bill_detail")
public class BillDetail {
@EmbeddedId
private BillMenuItemID billMenuItemID = new BillMenuItemID();
@ManyToOne
@MapsId("billId")
@JoinColumn(name = "bill_id")
private Bill bill;
@ManyToOne
@MapsId("menuItemId")
@JoinColumn(name = "menu_item_id")
private MenuItem menuItem;
@Column
private Long quantity;
@Column
private Double subtotal;
GET method
@GetMapping
public List<Bill> getMenuItems() {
return billService.getBills();
}
public List<Bill> getBills() {
return billRepository.findAll();
}
public interface BillRepository extends JpaRepository<Bill, Long> {
}
Database database
CodePudding user response:
In the class MenuItem
you should add the annotation @JsonIgnore
to prevent an infinite loop in the JSON format returned; a bill has a BillDetails , a BillDetails has a MenuItem , a MenuItem Has a BillDetails , every BillDetail has a List of MenuItem ...
@Entity
@Table(name = "menuItem",
uniqueConstraints = {
@UniqueConstraint(name = "menu_item_name_unique", columnNames = "name")
}
)
public class MenuItem {
@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
@Column(name = "menu_item_id")
private Long id;
private ItemType type;
private String name;
private String description;
private String imgUrl;
private Double price;
private MenuItemStatus status = MenuItemStatus.ENABLED;
// ADD JSON IGNORE ANNOTATION HERE :
@JsonIgnore
@OneToMany(mappedBy = "menuItem", cascade = CascadeType.ALL)
private List<BillDetail> billDetails = new ArrayList<>();