英文:
OneToMany relationship creating extra table in Spring boot 3 and JPA
问题
这里我使用Spring Boot 3.0.6和JPA。当我尝试在两个表之间创建OneToMany关系时,JPA会创建另一个表来维护关系。
我有两个实体类OrderEntity
和OrderItemsEntity
。OrderEntity
可以有多个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_items
、orders
、orders_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 OrderEntity
and 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?
答案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="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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论