JPA学习记录六(JPA中的一对多双向关联与级联操作)

本文详细探讨了JPA中双向一对多关联的实现,以购物订单和订单项为例,阐述了两者之间的关系。同时,介绍了级联操作如refresh、merge、remove和persist在不同场景下的应用,并讨论了默认加载方式和外键约束的设置。在订单表与订单项表的关联中,明确了关系维护端和被维护端的角色以及如何进行级联操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进行学习双向的一对多关联与级联操作:

案例:

     购物中的 订单表      订单项的表

订单表存放的是    : 订单号 和 总价钱

订单项表存放的是  : 在订单表中每一个订单号   对应的   商品信息

                                        一个订单号可能对应多个订单项,所以订单表和订单项表是双向的一对多的关系


思考级联操作:(refresh 刷新 merge   合并  remove 移除 persist 保存 )

refresh :应用场景  当通过find方法已经获得数据后,没有立即读取数据,而是去完成了其他的业务处理,然后重新读取刚刚获得的数据时,需要refresh,因为避免在这之前数据库的数据被修改,然后如果再一次通过find方法来获取,得到的是entitymanager中的一级缓存中的数据,并不是最新数据。

remove :级联删除

merge :级联合并

persist :级联保存

订单表----->订单项表:

persist:订单表执行persist方法时,也将把订单项保存到订单项表中

merge:当订单实体属于游离状态的时候,订单实体的属性被改变,然后订单项的属性也被改变,那么就需要merge方法一起同步更新到数据库中

               控制订单实体更新是否波及订单项实体的更新

remove:删除订单表时,执行remove方法时,也将订单表中删除所对应的订单号下的订单项删除

refresh: 为了获得最新数据,刷新订单表的同时,也重新获取最新的订单项数据


订单项表------>订单表:

merge:更新产品的价钱时,整个订单的总价钱会发生改变,此时就应该采用级联更新

refresh:级联刷新

默认加载方式:

当关系结尾是:Many 默认加载方式为 延迟加载   :访问延迟属性的时候必须确定entityManager实体没有被关闭

当关系结尾是:One默认加载方式为 立即加载

外键约束添加:

在JPA中约定:

1-m

     多的一方为关系维护端,关系维护端负责外键记录的更新,关系被维护端是没有权力更新外键记录。

所以应该在订单项表定义外键约束


编码如下:

订单表:Order

package cn.zl.bean;

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.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name="orders")//Order是数据库的关键字,所以重新定义数据表名字
public class Order {

	private String orderid;//订单号
	private Float amount=0f;
	private Set<OrderItem> items=new HashSet<OrderItem>();//定义了订单项列表
	@Id@Column(length=12)
	public String getOrderid() {
		return orderid;
	}
	public void setOrderid(String orderid) {
		this.orderid = orderid;
	}
	@Column(nullable=false)
	public Float getAmount() {
		return amount;
	}
	public void setAmount(Float amount) {
		this.amount = amount;
	}
	//@OneToMany(cascade={CascadeType.ALL})  //mappedBy 声明关系被维护端:值为关系维护端中是那个属性进行维护关系的。即OrderItem 中的 order属性
	@OneToMany(cascade={CascadeType.REFRESH,CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE},fetch=FetchType.LAZY,mappedBy="order")
	public Set<OrderItem> getItems() {
		return items;
	}
	public void setItems(Set<OrderItem> items) {
		this.items = items;
	}
	
	public void addOrderItem(OrderItem orderItem){
		orderItem.setOrder(this);
		this.items.add(orderItem);
	}

	
}




订单项表:

package cn.zl.bean;

import javax.persistence.CascadeType;
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;


@Entity
public class OrderItem {

	private Integer id;
	private String productName;
	private Float sellprice;
	private Order order;
	@Id
	@GeneratedValue
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	@Column(length=40,nullable=false)
	public String getProductName() {
		return productName;
	}
	public void setProductName(String productName) {
		this.productName = productName;
	}
	@Column(nullable=false)
	public Float getSellprice() {
		return sellprice;
	}
	public void setSellprice(Float sellprice) {
		this.sellprice = sellprice;
	}
	
	//optional 可选操作,为false 为不可选,不能为空
 @ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},fetch=FetchType.EAGER,optional=false)@JoinColumn(name="order_id")//外键列,对应的是orders表的orderid值
public Order getOrder() {return order;}public void setOrder(Order order) {this.order = order;}

编码测试:
package junit.test;

import static org.junit.Assert.*;

import java.util.UUID;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.junit.BeforeClass;
import org.junit.Test;

import cn.zl.bean.Order;
import cn.zl.bean.OrderItem;

public class OneToMany {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
	}

	@Test
	public void save() {
		EntityManagerFactory factory=Persistence.createEntityManagerFactory("persistUnitName");
		EntityManager em=factory.createEntityManager();
		em.getTransaction().begin();
		Order order = new Order();
		order.setAmount(34f);
		//order.setOrderid(UUID.randomUUID().toString());
		order.setOrderid("999");
		OrderItem orderItem1=new OrderItem();
		orderItem1.setProductName("足球");
		orderItem1.setSellprice(90f);
		
		OrderItem orderItem2=new OrderItem();
		orderItem2.setProductName("足球");
		orderItem2.setSellprice(90f);
		
		order.addOrderItem(orderItem1);
		order.addOrderItem(orderItem2);
		em.persist(order);
		em.getTransaction().commit();
		factory.close();
		
	}	@Test
	public void updateOrder() {
		EntityManagerFactory factory = Persistence.createEntityManagerFactory("persistUnitName");
	     EntityManager em = factory.createEntityManager();
	     em.getTransaction().begin();//开启事务
	     Order order=em.find(Order.class, "999");//managed 托管状态
	     order.setAmount(100f);
	     OrderItem orderItem = new OrderItem();
	     orderItem.setProductName("羽毛球");
	     orderItem.setSellprice(40f);
	     order.addOrderItem(orderItem);	     
	     em.merge(order);//把游离状态的实体bean同步到数据库
	     em.getTransaction().commit();
	     em.close();
	     factory.close();
	    
	}	@Test
	public void delete() {
		EntityManagerFactory factory=Persistence.createEntityManagerFactory("persistUnitName");
		EntityManager em=factory.createEntityManager();
		em.getTransaction().begin();
		Order order=em.find(Order.class, "999");
		em.remove(order); 
		em.getTransaction().commit();
		factory.close();
		
	}}

源码下载:http://download.csdn.net/detail/u013030488/9841964



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值