JPA:對映雙向一對多關聯關係
1.顧客實體類程式碼:
package com.wayne.helloworld;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
/*
* 如果不新增@Table註解,則表名與實體類名相同
*/
@Table(name="JPA_CUSTOMERS")
@Entity
public class Customer {
private Integer id;
private String lastName;
private String email;
private int age;
private Date createdDate;
private Date birthDay;
private Set<Order> orders=new HashSet<>();
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.AUTO)
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name="LAST_NAME",length=50,nullable=true)
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
//若屬性名與欄位名相同,則不需要填寫註解
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//精度時間戳
@Temporal(TemporalType.TIMESTAMP)
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
@Temporal(TemporalType.DATE)
public Date getBirthDay() {
return birthDay;
}
public void setBirthDay(Date birthDay) {
this.birthDay = birthDay;
}
//工具方法,不需要對映為某個資料庫表的一列
@Transient
public String getInfo(){
return "lastName:"+this.getLastName();
}
/*對映單向一對多的關係
使用OneToMany來對映一對多的關聯關係
使用JoinColumn來對映外來鍵列名稱
可以使用@OneToMany的fetch屬性來修改預設的載入策略
cascade={CascadeType.REMOVE}級聯刪除
*/
@JoinColumn(name="CUSTOMER_ID")
@OneToMany(fetch=FetchType.EAGER,cascade={CascadeType.REMOVE})
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
@Override
public String toString() {
return "Customer [id=" + id + ", lastName=" + lastName + ", email=" + email + ", age=" + age + ", createdDate="
+ createdDate + ", birthDay=" + birthDay + "]";
}
}
2.訂單實體類程式碼:
package com.wayne.helloworld;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Table(name="JPA_ORDERS")
@Entity
public class Order {
private Integer id;
private String orderName;
private Customer customer;
@GeneratedValue
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name="ORDER_NAME")
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
/*單向多對一的關聯關係
使用@ManyToOne來對映多對一的關聯關係
使用@JoinColumn來對映外來鍵
name為關聯表的列列名
可使用@ManyToOne的fetch屬性來修改預設的關聯屬性的載入策略*/
@JoinColumn(name="CUSTOMER_ID")
@ManyToOne(fetch=FetchType.LAZY)
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
.注意一點:@JoinColumn的name屬性要一致
3.新增資料測試程式碼以及控制檯輸出如下:
.先儲存"多"的一端,再儲存"一"的一端,預設情況下,會多出n條update語句
.先儲存"一"的一端,再儲存"多"的一端,程式碼片段以及控制檯輸出如下:
.可見會多出n/2的update語句.
4.在進行雙向"一"對"多"關聯關係時,建議使用"多"的一方來維護關聯關係,而"一"的一方不維護關係,這樣會有效減少sql語句
.讓"一"的一端放棄維護關聯關係,交給"多"的一端
.這裡注意要把@JoinColumn(name="CUSTOMER_ID")註釋掉,否則會報錯
(注意:若在"一"的一端的@OneToMany中使用mappedBy屬性,則@OneToMany端就不能使用@JoinColumn屬性)
.執行新增資料程式碼,控制檯如下輸出,沒有任何update語句: