SchemaGen 错误地生成了不必要的关联表

SchemaGen wrongly generates unnecessary association tables

我有一个非常简单的数据库模式,经典的 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;

似乎认为订单和orders_item[之间存在多对多关联=37=],以及 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;
    }
}
  • orders_orders_item table :

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

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 table。 orders_orders_item table 不会创建不必要的

  • product_orders_item table:

orders_itemproduct之间存在双向关系。您在 orders_item 端指定了 @JoinColumn。这导致在 orders_item table 上创建了 product_id 列,这是正确的。

但另一方面,由于您没有指定 mappedBy 并且它是双向关系,DB 试图通过创建 product_orders_item [=60= 来创建 link ].

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

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

    // ...

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

这表明双向关系已经在 productorders_item 之间创建(不需要映射 orders 字段)。不需要额外的 table 创建等。感谢 @JoinColumnproduct_id 列在 orders_item table.

中创建

你的联想:

@Entity
public class OrderEntity {

    @OneToMany
    private List<OrderItemEntity> orderItems;

    // ...
}

@Entity
public class ProductEntity {

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

    // ...
}

unidirectional@OneToMany。因此,正如文档中所述:

When using a unidirectional @OneToMany association, Hibernate resorts to using a link table between the two joining entities.

您可以通过添加 @JoinColumn 注释来更正它,正如@Hülya 回答中提到的那样。 (在 JPA 2.0). But bidirectional 中添加 @OneToMany 在管理集合持久化状态时效率更高。每次删除元素只需要一次更新(其中外键列设置为 NULL) .