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=],以及 product 和 orders_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_item
和product
之间存在双向关系。您在 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<>();
}
这表明双向关系已经在 product
和 orders_item
之间创建(不需要映射 orders
字段)。不需要额外的 table 创建等。感谢 @JoinColumn
,product_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
) .
我有一个非常简单的数据库模式,经典的 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=],以及 product 和 orders_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_item
和product
之间存在双向关系。您在 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<>();
}
这表明双向关系已经在 product
和 orders_item
之间创建(不需要映射 orders
字段)。不需要额外的 table 创建等。感谢 @JoinColumn
,product_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
) .