JPA -一对多双向联系关系与级联操作

JPA --------一对多双向关联与级联操作

Order.java

Java代码 JPA -一对多双向联系关系与级联操作
  1. package cn.itcast.bean;   
  2.   
  3. import java.util.HashSet;   
  4. import java.util.Set;   
  5.   
  6. import javax.persistence.CascadeType;   
  7. import javax.persistence.Column;   
  8. import javax.persistence.Entity;   
  9. import javax.persistence.GeneratedValue;   
  10. import javax.persistence.Id;   
  11. import javax.persistence.OneToMany;   
  12.   
  13. @Entity  
  14. public class Order {   
  15.     private String orderId;   
  16.     private Float amount = 0f;   
  17.     private Set<OrderItem> items = new HashSet<OrderItem>();   
  18.   
  19.     @Id      //要注意:目前JPA规范并没有提供UUID这种生成策略,目前主键值只提供了整型的生成方式,所以@GeneratedValue这个注解就不能在这里用上,不能对字符串进行id自增长。   
  20.     @Column(length = 12)   
  21.     public String getOrderId() {   
  22.         return orderId;   
  23.     }   
  24.   
  25.     public void setOrderId(String orderId) {   
  26.         this.orderId = orderId;   
  27.     }   
  28.   
  29.     @Column(nullable = false)   
  30.     public Float getAmount() {   
  31.         return amount;   
  32.     }   
  33.   
  34.     public void setAmount(Float amount) {   
  35.         this.amount = amount;   
  36.     }   
  37.   
  38.     @OneToMany(cascade = { CascadeType.REFRESH, CascadeType.PERSIST,   
  39.             CascadeType.MERGE, CascadeType.REMOVE })    //设置成一对多的关系。   
  40.     public Set<OrderItem> getItems() {   
  41.         return items;   
  42.     }   
  43.   
  44.     public void setItems(Set<OrderItem> items) {   
  45.         this.items = items;   
  46.     }   
  47. }  

 

OrderItem.java

Java代码 JPA -一对多双向联系关系与级联操作
  1. package cn.itcast.bean;   
  2.   
  3. import javax.persistence.Column;   
  4. import javax.persistence.Entity;   
  5. import javax.persistence.GeneratedValue;   
  6. import javax.persistence.Id;   
  7.   
  8. @Entity  
  9. public class OrderItem {   
  10.     private Integer id;   
  11.     private String productName;   
  12.     private Float sellPrice = 0f;   //默认值为0。   
  13.     private Order order;   
  14.   
  15.     @Id  
  16.     @GeneratedValue //id自增长方式生成主键。   
  17.     public Integer getId() {   
  18.         return id;   
  19.     }   
  20.   
  21.     public void setId(Integer id) {   
  22.         this.id = id;   
  23.     }   
  24.   
  25.     @Column(length = 40, nullable = false)   
  26.     public String getProductName() {   
  27.         return productName;   
  28.     }   
  29.   
  30.     public void setProductName(String productName) {   
  31.         this.productName = productName;   
  32.     }   
  33.   
  34.     @Column(nullable = false)   
  35.     public Float getSellPrice() {   
  36.         return sellPrice;   
  37.     }   
  38.   
  39.     public void setSellPrice(Float sellPrice) {   
  40.         this.sellPrice = sellPrice;   
  41.     }   
  42.   
  43.     public Order getOrder() {   
  44.         return order;   
  45.     }   
  46.   
  47.     public void setOrder(Order order) {   
  48.         this.order = order;   
  49.     }   
  50. }   



   在JPA里面,一对多关系(1-n):
   多的一方为关系维护端,关系维护端负责外键记录的更新(如果是条字段就负责字段的更新,如果是多对多关系中的中间表就负责中间表记录的更新),关系被维护端是没有权力更新外键记录(外键字段)的。


CascadeType的选项有,看图:
JPA -一对多双向联系关系与级联操作
 


     CascadeType.REFRESH:级联刷新,也就是说,当你刚开始获取到了这条记录,那么在你处理业务过程中,这条记录被另一个业务程序修改了(数据库这条记录被修改了),那么你获取的这条数据就不是最新的数据,那你就要调用实体管理器里面的refresh方法来刷新实体,所谓刷新,大家一定要记住方向,它是获取数据,相当于执行select语句的(但不能用select,select方法返回的是EntityManager缓存中的数据,不是数据库里面最新的数据),也就是重新获取数据。
     CascadeType.PERSIST:级联持久化,也就是级联保存。保存order的时候也保存orderItem,如果在数据库里已经存在与需要保存的orderItem相同的id记录,则级联保存出错。
     CascadeType.MERGE:  级联更新,也可以叫级联合并;当对象Order处于游离状态时,对对象Order里面的属性作修改,也修改了Order里面的orderItems,当要更新对象Order时,是否也要把对orderItems的修改同步到数据库呢?这就是由CascadeType.MERGE来决定的,如果设了这个值,那么Order处于游离状态时,会先update order,然后for循环update orderItem,如果没设CascadeType.MERGE这个值,就不会出现for循环update orderItem语句。
     所以说,级联更新是控制对Order的更新是否会波及到orderItems对象。也就是说对Order进行update操作的时候,orderItems是否也要做update操作呢?完全是由CascadeType.MERGE控制的。
     CascadeType.REMOVE:当对Order进行删除操作的时候,是否也要对orderItems对象进行级联删除操作呢?是的则写,不是的则不写。

    如果在应用中,要同时使用这四项的话,可以改成cascade = CascadeType.ALL

     应用场合问题:这四种级联操作,并不是对所有的操作都起作用,只有当我们调用实体管理器的persist方法的时候,CascadeType.PERSIST才会起作用;同样道理,只有当我们调用实体管理器的merge方法的时候,CascadeType.MERGE才会起作用,其他方法不起作用。    同样道理,只有当我们调用实体管理器的remove方法的时候,CascadeType.REMOVE才会起作用。
     注意: Query query = em.createQuery("delete from Person o where o.id=?1");这种删除会不会起作用呢?是不会起作用的,因为配置里那四项都是针对实体管理器的对应的方法。