JPA基础(十):JPA中的一对多关系

Order.java:

 1 import java.util.HashSet;
2 import java.util.Set;
3
4 import javax.persistence.CascadeType;
5 import javax.persistence.Column;
6 import javax.persistence.Entity;
7 import javax.persistence.FetchType;
8 import javax.persistence.Id;
9 import javax.persistence.OneToMany;
10 import javax.persistence.Table;
11
12 @Entity
13 @Table(name="orders")
14 public class Order {
15 @Id
16 private String orderId;
17 @Column(nullable=false)
18 private Float amount=0f;
19 @OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY,mappedBy="order")
20 private Set<OrderItem> items=new HashSet<OrderItem>();
21 public String getOrderId() {
22 return orderId;
23 }
24 public void setOrderId(String orderId) {
25 this.orderId = orderId;
26 }
27 public Float getAmount() {
28 return amount;
29 }
30 public void setAmount(Float amount) {
31 this.amount = amount;
32 }
33 public Set<OrderItem> getItems() {
34 return items;
35 }
36 public void setItems(Set<OrderItem> items) {
37 this.items = items;
38 }
39
40 }

OrderItem.java

 1 import javax.persistence.CascadeType;
2 import javax.persistence.Column;
3 import javax.persistence.Entity;
4 import javax.persistence.GeneratedValue;
5 import javax.persistence.Id;
6 import javax.persistence.JoinColumn;
7 import javax.persistence.ManyToOne;
8
9 @Entity
10 public class OrderItem {
11 @Id
12 @GeneratedValue
13 private Integer id;
14 @Column(length=40,nullable=false)
15 private String productName;
16 @Column(nullable=false)
17 private Float price=0f;
18 @ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},optional=false)
19 @JoinColumn(name="order_id")
20 private Order order;
21 public Integer getId() {
22 return id;
23 }
24 public void setId(Integer id) {
25 this.id = id;
26 }
27 public String getProductName() {
28 return productName;
29 }
30 public void setProductName(String productName) {
31 this.productName = productName;
32 }
33 public Float getPrice() {
34 return price;
35 }
36 public void setPrice(Float price) {
37 this.price = price;
38 }
39 public Order getOrder() {
40 return order;
41 }
42 public void setOrder(Order order) {
43 this.order = order;
44 }
45
46 }

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

 

CascadeType.REFRESH:级联刷新,也就是说,当你刚开始获取到了这条记录,那么在你处理业务过程中,这条记录被另一个业务程序修改了(数据库这条记录被修改了),那么你获取的这条数据就不是最新的数据,那你就要调用实体管理器里面的refresh方法来刷新实体,所谓刷新,大家一定要记住方向,它是获取数据,相当于执行select语句的(但不能用select,select方法返回的是EntityManager缓存中的数据,不是数据库里面最新的数据),也就是重新获取数据。
CascadeType.PERSIST:级联持久化,也就是级联保存。保存order的时候也保存orderItem,如果在数据库里已经存在与需要保存的orderItem相同的id记录,则级联保存出错。
CascadeType.MERGE: 级联更新,也可以叫级联合并;当对象Order处于游离状态时,对对象Order里面的属性作修改,也修改了Order里面的orderItems。
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");这种删除会不会起作用呢?是不会起作用的,因为配置里那四项都是针对实体管理器的对应的方法。

测试:

 1     @Test
2 public void save(){
3 EntityManagerFactory factory=Persistence.createEntityManagerFactory("sample");
4 EntityManager em=factory.createEntityManager();
5 em.getTransaction().begin();
6 Order order=new Order();
7 order.setAmount(100f);
8 order.setOrderId(UUID.randomUUID().toString());
9 OrderItem t1=new OrderItem();
10 t1.setPrice(10f);
11 t1.setProductName("test1");
12 t1.setOrder(order);
13 OrderItem t2=new OrderItem();
14 t2.setPrice(20f);
15 t2.setOrder(order);
16 t2.setProductName("test2");
17 order.getItems().add(t1);
18 order.getItems().add(t2);
19 em.persist(order);
20 em.getTransaction().commit();
21 em.close();
22 factory.close();
23 }

其中t1.setOrder(order);t2.setOrder(order);分别用来设置关系,如果不写的话order_id字段将为空,这也是mappedby的好处,因为你不用mappedby的话,控制权在一方,如果打开show_sql查看sql的话,或发现多出来update语句,那是很多余的,试想要是明细很多的话 那多出来得update很烦人- -,而且把控制端交给一方,意味着多方的关联字段必须不为空,否则会保存出错。



posted @ 2011-12-01 23:36  一直在等  阅读(5695)  评论(0编辑  收藏  举报