Understanding mappedBy annotation in Hibernate

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:

@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: 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: 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?

Now if I remove the mappedBy attribute and try to generate the tables, I see 3 tables this time:

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?

Now if I try to save a customer and its orders I get below DML operations:

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?

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.

Without, the relationship is external and Hibernate/JPA need to create another table to store the relationship.

Example:

A stackoverflow Question have several Answer.
An Answer is owned by one and only one Question.
In plain JDBC, you would create two table:

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

Where Question_ID is foreign key referencing Question.Question_ID.

A OneToMany has two main ways it can be accomplished in the database.

  • using a relation table (M:M)
  • using a foreign key in the target table. (1:M)

If you leave a OneToMany mapping and let it default, it will default to using 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 oposite 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.

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 joinColumncustomer_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.

Is normal this behavior mappedBy indicates only that the entity in this side is the inverse of the relationship, and the owner resides in the “other” entity.

I suggest you this link

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值