Java 理解Hibernate中的mappedBy注解
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25371481/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Understanding mappedBy annotation in Hibernate
提问by Chaitanya
I am trying to understand the mappedBy
attribute of @OneToMany
annotation in JPA. I created below example where a Customer has a list of Orders:
我想了解JPAmappedBy
中@OneToMany
注释的属性。我创建了以下示例,其中客户具有订单列表:
@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;
}
Now when I use Hibernate to generate the tables then I see that Hibernate created only 2 tables:
现在,当我使用 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
Also if I try to save a customer and some Orders I see below DML statements generated by Hibernate:
此外,如果我尝试保存客户和一些订单,我会在 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=?
Why hibernate tried to insert and updates the record in TBL_ORDER instead of just running a single insert query?
为什么 hibernate 试图在 TBL_ORDER 中插入和更新记录,而不是仅仅运行一个插入查询?
Now if I remove the mappedBy attribute and try to generate the tables, I see 3 tables this time:
现在,如果我删除了 mappingBy 属性并尝试生成表,这次我会看到 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
Why hibernate creates an additional table in this case? How the mappedBy attribute is controlling this? Why we have an additional unique key constraint on orders_id column in Customer_TBL_ORDER table?
为什么在这种情况下休眠会创建一个额外的表?mappingBy 属性是如何控制这个的?为什么我们在 Customer_TBL_ORDER 表中的 orders_id 列上有一个额外的唯一键约束?
Now if I try to save a customer and its orders I get below DML operations:
现在,如果我尝试保存客户及其订单,我会得到以下 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 (?, ?, ?)
Why we don't have an additional update query in this case compared to the case where I have declared the mappedBy attribute?
与我声明了mappedBy 属性的情况相比,为什么在这种情况下我们没有额外的更新查询?
采纳答案by NoDataFound
That's normal.
这是正常的。
With the mappedBy
, you directly tell Hibernate/JPA that one table owns the relationship, and therefore it is stored as a column of that table.
使用mappedBy
,您可以直接告诉 Hibernate/JPA 一个表拥有该关系,因此它被存储为该表的一列。
Without, the relationship is external and Hibernate/JPA need to create another table to store the relationship.
没有,关系是外部的,Hibernate/JPA 需要创建另一个表来存储关系。
Example:
例子:
- A stackoverflow
Question
have severalAnswer
. - An
Answer
is owned by one and only oneQuestion
.
- 一个 stackoverflow
Question
有几个Answer
. - An
Answer
由一个且仅一个拥有Question
。
In plain JDBC, you would create two table:
在普通 JDBC 中,您将创建两个表:
Questions(Question_ID, ...);
Answers(Answer_ID, Question_ID, ...);
Where Question_ID
is foreign key referencing Question.Question_ID
.
Question_ID
外键引用在哪里Question.Question_ID
。
As for the other case, I don't have a real case since there are almost every time many to many with a unique constraint(eg: a Question
may have several Answer
, and Answer
may have physically have several Question
, but appears only once for any Question
).
至于另一种情况,我没有真正的案例,因为几乎每次都有多对多的唯一约束(例如:aQuestion
可能有几个Answer
,并且Answer
可能在物理上有几个Question
,但 any 只出现一次Question
)。
回答by Xstian
回答by Chris
A OneToMany
has two main ways it can be accomplished in the database.
AOneToMany
有两种主要方式可以在数据库中完成。
- using a relation table (M:M)
- using a foreign key in the target table. (1:M)
- 使用关系表 (M:M)
- 在目标表中使用外键。(1:M)
If you leave a OneToMany
mapping and let it default, it will by default use a relation table, which is what you seem to want. If you don't want a join table to be used, you would either specify a JoinColumn
which sets up a foreign key relationship much like a OneToOne
, but in the opposite direction - it tells the provider what field in the target table points to this entity's primary key. But commonly the target foreign key is mapped in the target entity - it is a ManyToOne
after all - and so the mappedby
is used to specify that this OneToMany
should use the relationship already defined in the target entity.
如果你留下一个OneToMany
映射并让它默认,它会默认使用一个关系表,这就是你想要的。如果您不想使用连接表,您可以指定 aJoinColumn
来设置外键关系,就像 a 一样OneToOne
,但方向相反 - 它告诉提供者目标表中的哪个字段指向该实体的主字段钥匙。但通常目标外键映射在目标实体中 -ManyToOne
毕竟它是一个- 因此mappedby
用于指定这OneToMany
应该使用已经在目标实体中定义的关系。
In this case, mappedBy=customer
tells it to look at the customer
property mapping within the Order entity. There, it finds customer has a ManyToMany
mapping with a default joinColumn customer_id
that it also uses for the OneToMany
. Because it is already mapped within the Order entity, the OneToMany
is read-only. This ensures that should the two relationships be out of sync, JPA
has one side to always trust and use to set the database field.
在这种情况下,mappedBy=customer
告诉它查看customer
Order 实体中的属性映射。在那里,它发现 customer 有一个ManyToMany
带有默认 joinColumn的映射customer_id
,它也用于OneToMany
. 因为它已经映射到 Order 实体中,所以它OneToMany
是只读的。这确保了如果这两个关系不同步,JPA
则有一方始终信任并用于设置数据库字段。