OneToMany关系在Spring Boot 3和JPA中创建额外的表格

huangapple go评论62阅读模式
英文:

OneToMany relationship creating extra table in Spring boot 3 and JPA

问题

这里我使用Spring Boot 3.0.6和JPA。当我尝试在两个表之间创建OneToMany关系时,JPA会创建另一个表来维护关系。

我有两个实体类OrderEntityOrderItemsEntityOrderEntity可以有多个OrderItemsEntity。因此,关系是OneToMany。

让我们看一下代码片段。

OrderEntity.java

@Entity
@Table(name = "orders")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class OrderEntity {
    // ...(略)
    @OneToMany(cascade = CascadeType.ALL)
    private List<OrderItemsEntity> items;
}

OrderItemsEntity.java

@Entity
@Table(name = "order_items")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class OrderItemsEntity {
    // ...(略)
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private OrderEntity orders;
}

到目前为止,对我来说一切都没问题,但当我检查数据库时,我发现Hibernate已经创建了3个表order_itemsordersorders_items。最后一个表orders_items用于在两个表之间创建关系。

这是orders_items的DDL(数据定义语言):

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

我已经尝试使用mappedBy@JoinColumn注解。在这种情况下,不会生成额外的表,但我在连接列中没有获得任何数据。这就是为什么表连接没有发生的原因。

为什么JPA在OneToMany关系中创建另一列?如何在没有另一个表的情况下实现列连接?

英文:

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 = &quot;orders&quot;)
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class OrderEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String orderNumber;
    @OneToMany( cascade = CascadeType.ALL)
    private List&lt;OrderItemsEntity&gt; items;
}

OrderItemsEntity.Java class

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

@Entity
@Table(name = &quot;order_items&quot;)
@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?

答案1

得分: 1

这是正确的OrderItemsEntity代码,如果你不想创建附加的表格:

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

如果连接无效,请检查你的服务类。与OrderEntity的关系必须在持久化OrderItemsEntity之前设置,就像这样:

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

请注意:为了更好的性能,最好使用Set而不是List来表示实体关系。

请注意2:附加的注解@JsonBackReference和@ToString.Exclude可防止在调用Lombok生成的toString方法和/或JSON序列化时产生无限循环。如果合适,请添加。

英文:

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

@ManyToOne(mappedBy=&quot;items&quot; 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.

huangapple
  • 本文由 发表于 2023年5月22日 19:32:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76305734.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定