了解Hibernate中的mappedBy注释
我试图理解JPA中@OneToMany
注释的mappedBy
属性。 我创建了以下示例,其中Customer有一个Orders列表:
@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 getOrders() { return orders; } public void setOrders(List orders) { this.orders = orders; } private List 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会在这种情况下创建一个额外的表? mappedBy属性如何控制它? 为什么我们在Customer_TBL_ORDER表中的orders_id列上有一个额外的唯一键约束?
现在,如果我尝试保存客户及其订单,我将接受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 (?, ?, ?)
与我声明mappedBy属性的情况相比,为什么我们在这种情况下没有额外的更新查询?
这很正常。
使用mappedBy
,您可以直接告诉Hibernate / JPA一个表拥有该关系,因此它存储为该表的一列。
没有,关系是外部的,Hibernate / JPA需要创建另一个表来存储关系。
例:
- stackoverflow
Question
有几个Answer
。 -
Answer
由一个且仅一个Question
。
在纯JDBC中,您将创建两个表:
Questions(Question_ID, ...); Answers(Answer_ID, Question_ID, ...);
其中Question_ID
是引用Question.Question_ID
外键。
至于另一种情况,我没有一个真实的案例,因为几乎每次都有多个具有唯一约束的人 (例如:一个Question
可能有几个Answer
,而Answer
可能有几个Question
,但只出现一次对于任何Question
)。
OneToMany
有两种主要方式可以在数据库中完成。
- 使用关系表(M:M)
- 在目标表中使用外键。 (1:M)
如果您保留OneToMany
映射并将其设置为默认值,则默认情况下它将使用关系表,这是您似乎想要的。 如果你不想使用连接表,你可以指定一个JoinColumn
来设置一个外键关系,就像OneToOne
,但是方向相反 – 它告诉提供者目标表中的哪个字段指向这个实体的主键。 但通常目标外键映射在目标实体中 – 毕竟它是ManyToOne
– 因此mappedby
用于指定此OneToMany
应使用已在目标实体中定义的关系。
在这种情况下, mappedBy=customer
告诉它查看Order实体中的customer
属性映射。 在那里,它发现客户有一个ManyToMany
映射,其默认的joinColumn customer_id
也用于OneToMany
。 因为它已经在Order实体中映射,所以OneToMany
是只读的。 这确保了如果两个关系不同步, JPA
有一方始终信任并用于设置数据库字段。
正常此行为mappedBy
仅表示此方面的实体是关系的反转,并且所有者驻留在“其他”实体中。
我建议你这个链接
- 如何在Hibernate中设置内部查询的限制?
- 使用Hibernate / Spring / JUnit设置和删除复杂数据库状态
- Hibernate查询多次给出相同的记录
- 是否可以在Hibernate / JPA中动态定义列名?
- org.codehaus.jackson.map.JsonMappingException:无限递归(StackOverflowError)
- 在使用Spring和Hibernate时是否需要persistence.xml?
- Hibernate批处理有什么用?
- JSF + Hibernate:Collection与任何会话无关
- 尽管有OpenSessionInViewFilter,但仍然存在LazyInitializationException