一、單向多對一關系:
@Entity
@Table(name="jpa_order")
public class Order {
private Integer id;
private String orderName;
private Customer customer;
@GeneratedValue(strategy=GenerationType.AUTO)
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
@JoinColumn(name="customer_id")
@ManyToOne
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
二、單向一對多關系:
@Table(name="jpa_customer")
@Entity
public class Customer {
private Integer id;
private String lastName;
private String email;
private Integer age;
private Date birthday;
private Date createTime;
private Set<Order> orders = new HashSet<>();
@GeneratedValue(strategy=GenerationType.AUTO)
@Id
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name="last_name")
public String getLastName() {
return lastName;
}
@Temporal(TemporalType.DATE)
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Temporal(TemporalType.TIMESTAMP)
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@JoinColumn(name="customer_id")
@OneToMany(cascade=CascadeType.REMOVE)
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
}
1、插入
不管先插入多大一端還是一的一端,最終打印的sql語句數量是一樣的,因為是由一的一端維護關聯關系,所以在插入多的一端時它並不會保存外鍵值,只有在持久化之后再另外發送update語句更新多的一端的外鍵值
2、刪除
多的一端可以隨意刪除,主要說一下一的一端
在單向多對一的時候一的一端是不可以刪除的
而單項一對多的不同,可以刪除一的一端,那么多的一端會被怎么操作呢?根據發出的sql語句可以看出,在默認情況下,刪除一的一端,多的一端的外鍵會被置為null。那么接下來就說一下怎么設置對多的一端的操作。
3、在@OneToMany注解中有一個cascade屬性,它的值是一個CascadeType類的數組
ALL :級聯所有實體狀態轉換
PERSIST :級聯實體持久化操作。
MERGE :級聯實體合並操作。
REMOVE :級聯實體刪除操作。
REFRESH :級聯實體刷新操作。
DETACH :級聯實體分離操作。
二、雙向一對一關系: 一個部門有一個經理,一個經理管一個部門
1、department類
@Entity
@Table(name="jpa_department")
public class Department {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
@Column(name="dep_name")
private String depName;
@JoinColumn(name="manager_id")
@OneToOne
private Manager manager;
}
2、Manager類
@Entity
@Table(name="jpa_manager")
public class Manager {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
private String name;
@OneToOne(mappedBy="manager")
private Department department;
}
3、插入:
Manager manager = new Manager();
manager.setName("王強");
Department department = new Department();
department.setDepName("銷售部");
manager.setDepartment(department);
department.setManager(manager);
entityManager.persist(manager);
entityManager.persist(department);
關於插入的順序,先插入不維護關聯關系的一方,即manager(沒有外鍵的一方)
4、查詢:查詢維護關聯關系的一方(有外鍵的一方)
Department dept = entityManager.find(Department.class, 1);
System.out.println(dept.getDeptName());
如果只想要department,不想要manager。可以用fetch更改為懶加載策略:在department實體類中加入
@OneToOne(fetch=FetchType.LAZY)
private Manager manager;
5、查詢不維護關聯關系的一方(沒有外鍵的一方)
Manager m = entityManager.find(Manager.class, 1);
System.out.println(m.getName());
運行發現,查詢manager時,一定會去查department,即使用fetch改為懶加載策略,結果也是一樣的。
不同的時,如果改為懶加載,將會執行兩個sql語句查詢。默認情況下是執行一句sql語句關聯查詢。因此不推薦設置fetch
注意: 一定會查詢兩個對象的原因:
(1) 在查詢manager表時,沒有外鍵,jpa不知道該怎么處理Manager中的關聯對象,因此它一定會去department表中查看有沒有相應的記錄。
(2) 在查詢department時,因為有外鍵,所以jpa很容易的知道該怎么處理關聯對象:要么返回一個代理,要么返回對象)