首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SchemaGen错误地生成不必要的关联表

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

Stack Overflow用户
提问于 2021-02-21 12:28:13
回答 2查看 56关注 0票数 2

我有一个非常简单的DB模式,经典的顺序--(一对多)--> OrderItem <--(多对一)--产品

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

代码语言:javascript
复制
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之间有很多关联。

为什么会发生这种情况?

我的实体类如下所示:

命令:

代码语言:javascript
复制
@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;
    }
}

订单项目:

代码语言:javascript
复制
@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;
    }
}

产品:

代码语言:javascript
复制
@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;
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-02-21 13:26:43

  • orders_orders_item表:

由于您没有指定@JoinColumn,而不是只指定一个外键,因此将创建一个包含两个外键的额外表。

代码语言:javascript
复制
orders_orders_item (OrderEntity_order_id, orderItems_orders_item_id) 

要解决这个问题,应该将@JoinColumn注释添加到OrderEntity中。

代码语言:javascript
复制
@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_itemproduct之间存在双向关系。您在@JoinColumn端指定了orders_item。这导致在product_id表上创建了orders_item列,这是正确的。

但是另一方面,由于您没有指定mappedBy,而且它是一个双向关系,DB试图通过创建product_orders_item表来创建链接。

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

代码语言:javascript
复制
@Entity
@Table(name = "product")
public class ProductEntity {

    // ...

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

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

票数 1
EN

Stack Overflow用户

发布于 2021-02-21 14:50:12

你们的协会:

代码语言:javascript
复制
@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回答中提到过。(在JPA2.0中添加)。但是,双向 @OneToMany在管理集合持久性状态时效率要高得多。每个元素删除只需要一个更新(其中外键列设置为NULL)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66302300

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档