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

猜你喜欢

转载自blog.csdn.net/weixin_40740613/article/details/84317023