当前位置: 首页 > 知识库问答 >
问题:

理解Hibernate中的mappedBy注释

闾丘高峰
2023-03-14

我试图理解JPA中@OneToMany注释的mappedBy属性。我创建了以下示例,其中客户有一个订单列表:

@Entity
public class Customer {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;

   @OneToMany(mappedBy="customer")
   @OrderColumn(name="orders_index")
   public List<Order> getOrders() { return orders; }
   public void setOrders(List<Order> orders) { this.orders = orders; }
   private List<Order> orders;
}

@Entity
@Table(name="TBL_ORDER")
public class Order {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;

   public int getOrderNumber() { return orderNumber; }
   public void setOrderNumber(int orderNumber) { this.orderNumber = orderNumber; }
   private int orderNumber;

   @ManyToOne
   public Customer getCustomer() { return customer; }
   public void setCustomer(Customer customer) { this.customer = customer; }
   private Customer customer;
}

现在,当我使用Hibernate生成表时,我看到Hibernate只创建了2个表:

Hibernate: create table Customer (id number(10,0) not null, primary key (id))
Hibernate: create table TBL_ORDER (id number(10,0) not null, orderNumber number(10,0) not null, customer_id number(10,0), orders_index number(10,0), primary key (id))
Hibernate: alter table TBL_ORDER add constraint FK_nt24krtgqwcsynosqgk4jkvfv foreign key (customer_id) references Customer

另外,如果我试图保存一个客户和一些订单,我会看到下面由Hibernate生成的DML语句:

Hibernate: insert into Customer (id) values (?)
Hibernate: insert into TBL_ORDER (customer_id, orderNumber, id) values (?, ?, ?)
Hibernate: update TBL_ORDER set orders_index=? where id=?

为什么hibernate尝试在TBL_ORDER中插入和更新记录,而不是仅仅运行一个插入查询?

现在,如果我删除mappedBy属性并尝试生成表,那么这次我会看到3个表:

Hibernate: create table Customer (id number(10,0) not null, primary key (id))
Hibernate: create table Customer_TBL_ORDER (Customer_id number(10,0) not null, orders_id number(10,0) not null, orders_index number(10,0) not null, primary key (Customer_id, orders_index))
Hibernate: create table TBL_ORDER (id number(10,0) not null, orderNumber number(10,0) not null, customer_id number(10,0), primary key (id))
Hibernate: alter table Customer_TBL_ORDER add constraint UK_sw94jktvh72tripj876s31052  unique (orders_id)
Hibernate: alter table Customer_TBL_ORDER add constraint FK_sw94jktvh72tripj876s31052 foreign key (orders_id) references TBL_ORDER
Hibernate: alter table Customer_TBL_ORDER add constraint FK_f03up2h945cg0dcbo2pdb1d3c foreign key (Customer_id) references Customer
Hibernate: alter table TBL_ORDER add constraint FK_nt24krtgqwcsynosqgk4jkvfv foreign key (customer_id) references Customer

为什么在这种情况下hibernate会创建一个额外的表?这个属性是如何控制的?为什么我们有一个额外的唯一键约束orders_idCustomer_TBL_ORDER表中的列?

现在,如果我试图保存一个客户及其订单,我会得到以下DML操作:

Hibernate: insert into Customer (id) values (?)
Hibernate: insert into TBL_ORDER (customer_id, orderNumber, id) values (?, ?, ?)
Hibernate: insert into Customer_TBL_ORDER (Customer_id, orders_index, orders_id) values (?, ?, ?)

为什么在这种情况下,我们没有一个额外的更新查询相比,我已经声明了mappdBy属性的情况下?

共有3个答案

田宇
2023-03-14

此行为mappdBy仅指示此端中的实体是关系的反义词,并且所有者驻留在其他实体中。

我建议你使用这个链接

吴修洁
2023-03-14

OneToMany有两种主要的方法可以在数据库中实现。

  1. 使用关系表(M:M)

如果您保留一个OneToMany映射并将其设为默认值,它将默认使用一个关系表,这似乎是您想要的。如果不希望使用联接表,可以指定一个JoinColumn,它设置外键关系,就像OneToOne,但方向相反-它告诉提供者目标表中的哪个字段指向该实体的主键。但通常目标外键映射到目标实体中-毕竟它是一个manytone,因此mappedby用于指定此OneToMany应使用目标实体中已定义的关系。

在这种情况下,mappedBy=customer告诉它查看订单实体中的customer属性映射。在那里,它发现customer有一个manytomy映射,其中有一个默认的joinColumncustomer\u id,它也用于OneToMany。因为它已经映射到订单实体中,OneToMany是只读的。这确保了如果这两个关系不同步,JPA有一个始终信任的方面,并用于设置数据库字段。

翟淮晨
2023-03-14

这很正常。

使用mappedBy,您可以直接告诉Hibernate/JPA一个表拥有该关系,因此它被存储为该表的一列。

如果没有,关系是外部的,Hibernate/JPA需要创建另一个表来存储关系。

示例:

  • 一个堆栈溢出问题有几个答案

在普通JDBC中,您将创建两个表:

Questions(Question_ID, ...);
Answers(Answer_ID, Question_ID, ...);

其中Question\u ID是外键引用Question。问题_ID

至于另一种情况,我没有一个真正的情况,因为几乎每次都有多对多的唯一约束(例如:一个问题可能有几个答案,而答案可能物理上有几个问题,但对于任何问题)只出现一次。

 类似资料:
  • 根据Hibernate留档,注释的解释如下: 在嵌入式id对象中,关联表示为关联实体的标识符。但您可以通过@MapsId注释将其值链接到实体中的常规关联。@MapsId值对应于包含关联实体标识符的嵌入式id对象的属性名称。在数据库中,这意味着客户。用户和客户ID。userId属性共享相同的基础列(本例中为user\u fk)。 它还说: 虽然JPA不支持Hibernate,但它允许您将关联直接放置

  • nexr@Entity公共类产品{ 错误:

  • 我有4个表kode_pos、korwil、user和WAFAT。在Korwil类中,它保存来自user的外键,并将主键交给kode_pos,这意味着在Korwil类@OneToOne和@OneToMany中有两个映射, 我有个错误 org.hibernate.AnnotationException:在:org.ppbni.splatter.model.useradmin.korwil中未知mapp

  • 问题内容: 需要使用一对多和多对一关系。这是我对象中的双向关系,因此我可以从任一方向来回移动。是推荐的解决方法,但是,我听不懂。有人可以解释: 推荐的使用方式是什么? 它解决什么目的? 就我的示例而言,这是带有注释的类: 拥有许多 许多 属于一个 A 航空公司: 航空公司航班: 编辑: 数据库模式: AirlineFlights具有idAirline作为ForeignKey,而Airline没有i

  • 问题内容: 我试图了解JPA 中注释的属性。我在下面的示例中创建了一个客户具有订单列表的示例: 现在,当我使用Hibernate生成表时,我看到Hibernate仅创建了2个表: 另外,如果我尝试保存客户和一些订单,我会在下面看到由Hibernate生成的DML语句: 为什么Hibernate试图在TBL_ORDER中插入和更新记录,而不仅仅是运行单个插入查询? 现在,如果我删除mapledBy属

  • Hibernate留档在@BatchSize上提供了一些信息,如下所示: @BatchSize指定一个“批量大小”,用于按标识符获取此类实例。尚未加载的实例一次加载一个批大小(默认值为1)。 我不清楚这个注释的目的是什么,什么时候我们需要使用它。请帮助我理解何时使用这个注释。