2

我有一个非常简单的数据库模式,经典的Order ---(一对多)---> OrderItem <---(多对一)--- Product

但是,当我使用 SchemaGen 生成 DDL 时,它会创建一个额外的层orders_orders_item 和 product_orders_item,实际上添加了一个冗余的关联表层:

create table orders (order_id bigint not null auto_increment, order_amout varchar(255), primary key (order_id)) engine=InnoDB;
create table orders_item (orders_item_id bigint not null auto_increment, order_amount integer, product_id bigint not null, primary key (orders_item_id)) engine=InnoDB;
create table orders_orders_item (OrderEntity_order_id bigint not null, orderItems_orders_item_id bigint not null) engine=InnoDB;
create table product (id bigint not null auto_increment, name varchar(255), price decimal(19,2), primary key (id)) engine=InnoDB;
create table product_orders_item (ProductEntity_id bigint not null, orders_orders_item_id bigint not null) engine=InnoDB;

似乎认为ordersorders_item之间以及productorders_item之间存在多对多关联。

为什么会这样?

我的实体类如下所示:

订单 :

@Entity
@Table(name = "orders")
public class OrderEntity {

    @Id
    @Column(name = "order_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @OneToMany
    private List<OrderItemEntity> orderItems;

    protected OrderEntity() {
    }

    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public List<OrderItemEntity> getOrderItems() {
        return orderItems;
    }
    public void setOrderItems(List<OrderItemEntity> orderItems) {
        this.orderItems = orderItems;
    }
}

订单项目:

@Entity
@Table(name = "orders_item")
public class OrderItemEntity {

    @Id
    @Column(name = "orders_item_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    @JoinColumn(name = "product_id", nullable = false, updatable = false)
    private ProductEntity product = new ProductEntity();

    @Column(name = "order_amount")
    private int amount;

    protected OrderItemEntity() {
    }

    public OrderItemEntity(ProductEntity product, int amount) {
        super();
        this.product = product;
        this.amount = amount;
    }
    public int getAmount() {
        return amount;
    }
    public void setAmount(int amount) {
        this.amount = amount;
    }
    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public ProductEntity getProduct() {
        return product;
    }
    public void setProduct(ProductEntity product) {
        this.product = product;
    }
}

产品 :

@Entity
@Table(name = "product")
public class ProductEntity {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @OneToMany
    private List<OrderItemEntity> orders = new ArrayList<>();

    @Column(name = "name")
    private String name;

    @Column(name = "price")
    private BigDecimal price;

    protected ProductEntity() {
    }

    public ProductEntity(String name) {
        this.name = name;
    }

    public ProductEntity(String name, BigDecimal price) {
        super();
        this.name = name;
        this.price = price;
    }

    public long getId() {
        return id;
    }
    public void setId(long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public BigDecimal getPrice() {
        return price;
    }
    public void setPrice(BigDecimal price) {
        this.price = price;
    }
}
4

2 回答 2

1

您的协会:

@Entity
public class OrderEntity {

    @OneToMany
    private List<OrderItemEntity> orderItems;

    // ...
}

@Entity
public class ProductEntity {

    @OneToMany
    private List<OrderItemEntity> orders = new ArrayList<>();

    // ...
}

单向 @OneToMany的。因此,正如文档中所述:

当使用单向@OneToMany关联时,Hibernate 使用两个连接实体之间的链接表。

您可以通过添加@JoinColumn@Hülya 答案中提到的注释来更正它。(它是在JPA 2.0中添加的)。但是在管理集合持久性状态时,双向 @OneToMany的效率要高得多。每个元素删除只需要一次更新(其中外键列设置为NULL)。

于 2021-02-21T14:50:12.847 回答
1
  • orders_orders_item桌子 :

由于您没有指定@JoinColumn,而不是只有一个外键,而是创建了一个带有两个外键的额外表。

orders_orders_item (OrderEntity_order_id, orderItems_orders_item_id) 

要解决此问题,您应该将@JoinColumn注释添加到OrderEntity.

@Entity
@Table(name = "orders")
public class OrderEntity {

    //...

    @OneToMany
    @JoinColumn(name = "order_id")
    private List<OrderItemEntity> orderItems;
}

使用此映射,只会将一order_id列添加到orders_item表中。orders_orders_item不会不必要地创建表

  • product_orders_item桌子:

orders_item和之间存在双向关系product。你@JoinColumnorders_item旁边指定。这导致在正确的表product_id上创建列。orders_item

但是另一方面,由于您没有指定mappedBy并且它是双向关系,因此数据库尝试通过创建product_orders_item表来建立链接。

您应该将mappedBy属性添加到orders字段。

@Entity
@Table(name = "product")
public class ProductEntity {

    // ...

    @OneToMany (mappedBy="product")
    private List<OrderItemEntity> orders = new ArrayList<>();
}

product这表明已经在and之间创建了双向关系orders_item(无需映射orders字段)。不需要额外的表创建等。感谢 ,@JoinColumn在表product_id中创建列orders_item

于 2021-02-21T13:26:43.897 回答