Search code examples
springspring-boothibernatejpaone-to-many

OneToMany relationship creating extra table in Spring boot 3 and JPA


Here I am working with Spring boot 3.0.6 and JPA. When I am trying to create OnToMany relationship among two table then JPA is creating another table to mentaining the relationship.

I have two entity class OrderEntityand OrderItemsEntity. OrderEntity could have many Items. So the relationship is OneToMany.

Let's see the code segment.

OrderEntity.java

import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.List;

@Entity
@Table(name = "orders")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class OrderEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String orderNumber;
    @OneToMany( cascade = CascadeType.ALL)
    private List<OrderItemsEntity> items;
}

OrderItemsEntity.Java class

import jakarta.persistence.*;
import java.math.BigDecimal;

@Entity
@Table(name = "order_items")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class OrderItemsEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String skuCode;
    private BigDecimal price;
    private Integer quantity;
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private OrderEntity orders;
}

Till now everything is OK to me, But when I check the database, I have found that Hibernate has created 3 table order_items, orders, orders_items. The last table orders_items is using to creating the relation among two tables.

Here is the DDL of orders_items

CREATE TABLE `orders_items` (
  `order_entity_id` bigint NOT NULL,
  `items_id` bigint NOT NULL,
  UNIQUE KEY `UK_7qrg5pfgjon82yhgwfqrdijm5` (`items_id`),
  KEY `FKk3469jf6jqgaby5mbuyteg08e` (`order_entity_id`),
  CONSTRAINT `FKk3469jf6jqgaby5mbuyteg08e` FOREIGN KEY (`order_entity_id`) REFERENCES `orders` (`id`),
  CONSTRAINT `FKol66sj9j6lm31o8rea1gw8ij0` FOREIGN KEY (`items_id`) REFERENCES `order_items` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

I have tried with maped by and @joinedColum annotation. In that case the aditional table is not genarating. But I am not getting any data in the join column. That is why table joinig is no happening.

Why JPA is creating another column in OneToMany relationship. And how can I implement column joining without another table?


Solution

  • This is the correct code of OrderItemsEntity if you don't want the additional table to be created:

    @ManyToOne(mappedBy="items" fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JsonBackReference
    @ToString.Exclude
    private OrderEntity orders;
    

    If the join doesn't work then you should check your service class. The relation to OrderEntity must be set prior to persisting of OrderItemsEntity like this:

    OrderEntity order = orderRepository.findById(existingOrderId);
    OrderItemsEntity item = new OrderItemsEntity();
    item.setOrders(order);
    itemRepository.save(item);
    

    Please note: for better performance it is better to use Set instead of List for the entity relationships.

    Please note 2: the additional annotations @JsonBackReference and @ToString.Exclude prevent an infinite loop while calling Lombok generated toString method and/or JSON serialization. Please add if appropriate.