1. 程式人生 > >JPA:對映雙向一對多關聯關係

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語句: