JPA映射关联关系-单向一对多

来源:互联网 发布:淘宝的鞋子是正品吗 编辑:程序博客网 时间:2024/05/21 07:24

JPA映射关联关系-单向一对多

单向一对多关联

在实际开发过程中,JPA一对多的单向关联使用的情况并不多。

下面是顾客与订单的配置。
顾客(Customer):一的一方,进行OneToMany配置
订单项(Order):多的一方,不需要做任何配置


各自的实体类如下:

package com.ppl.entity;import java.util.Date;import java.util.HashSet;import java.util.Set;import javax.persistence.Cacheable;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;@Cacheable(true)@Table(name = "JPA_CUTOMERS")@Entitypublic class Customer {private Integer id;private String lastName;private String email;private int age;private Date createdTime;private Date birth;//一对多使用private Set<Order> orders = new HashSet<>();//映射单向 1-n 的关联关系//使用 @OneToMany 来映射 1-n 的关联关系//使用 @JoinColumn 来映射外键列的名称//可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略//可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略. //注意: 若在 1 的一端的 @OneToMany 中使用 mappedBy 属性, 则 @OneToMany 端就不能再使用 @JoinColumn 属性了.     @JoinColumn(name="CUSTOMER_ID")    @OneToMany//@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.REMOVE},mappedBy="customer")public Set<Order> getOrders() {return orders;}public void setOrders(Set<Order> orders) {this.orders = orders;}public Customer() {// TODO Auto-generated constructor stub}public Customer(String lastName, int age) {super();this.lastName = lastName;this.age = age;}@GeneratedValue(strategy = GenerationType.AUTO)@Idpublic Integer getId() {return id;}public void setId(Integer id) {this.id = id;}@Column(name = "LAST_NAME", length = 50, nullable = false)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;}public Date getCreatedTime() {return createdTime;}public void setCreatedTime(Date createdTime) {this.createdTime = createdTime;}public Date getBirth() {return birth;}public void setBirth(Date birth) {this.birth = birth;}@Overridepublic String toString() {return "Customer [id=" + id + ", lastName=" + lastName + ", email=" + email + ", age=" + age + "]";}}

package com.ppl.entity;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Table;@Table(name = "JPA_ORDERS")@Entitypublic class Order {private Integer id;private String orderName;// 多对一使用// private Customer customer;@GeneratedValue@Idpublic 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;}// //映射单向 n-1 的关联关系// //使用 @ManyToOne 来映射多对一的关联关系// //使用 @JoinColumn 来映射外键. (数据库中外键的名字为CUSTOMER_ID )// //可使用 @ManyToOne 的 fetch 属性来修改默认的关联属性的加载策略// @JoinColumn(name="CUSTOMER_ID")// @ManyToOne(fetch=FetchType.LAZY)// //@ManyToOne()// public Customer getCustomer() {// return customer;// }//// public void setCustomer(Customer customer) {// this.customer = customer;// }}

一个User可以有多个Order,在Customer中有一个属性private Set<Order> orders = new HashSet<>();或者List<Order> orders ,这就是一对多关联关系。和多对一有些许不同。
一对多使用@OneToMany注解,外键关系还是使用@JoinColumn(name=”CUSTOMER_ID”)。
注意:这里的@JoinColumn(name=”CUSTOMER_ID”),虽然是写在Customer实体类中,在”CUSTOMER_ID”这个字段却是加在jpa_orders表中。

测试代码:

//单向 1-n 关联关系执行保存时, 一定会多出 UPDATE 语句.//因为 n 的一端在插入时不会同时插入外键列. @Testpublic void testOneToManyPersist(){Customer customer = new Customer();customer.setAge(18);customer.setBirth(new Date());customer.setCreatedTime(new Date());customer.setEmail("pplsunny@163.com");customer.setLastName("MM");Order order1 = new Order();order1.setOrderName("O-MM-1");Order order2 = new Order();order2.setOrderName("O-MM-2");//建立关联关系customer.getOrders().add(order1);customer.getOrders().add(order2);//执行保存操作entityManager.persist(customer);entityManager.persist(order1);entityManager.persist(order2);}

这里三个对象插入的顺序怎么调换结果都是一样的。这一点和多对一有一些不同。


查询

//映射单向 1-n 的关联关系//使用 @OneToMany 来映射 1-n 的关联关系//使用 @JoinColumn 来映射外键列的名称//可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略//可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略. //注意: 若在 1 的一端的 @OneToMany 中使用 mappedBy 属性, 则 @OneToMany 端就不能再使用 @JoinColumn 属性了.     @JoinColumn(name="CUSTOMER_ID")    @OneToMany//@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.REMOVE},mappedBy="customer")public Set<Order> getOrders() {return orders;}


//默认对关联的多的一方使用懒加载的加载策略. //可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略@Testpublic void testOneToManyFind(){Customer customer = entityManager.find(Customer.class, 8);System.out.println(customer.getLastName());System.out.println(customer.getOrders().size());}


一对多的查询,默认使用懒加载的加载策略,可以使用@OneToMany(fetch=FetchType.EAGER) 更改策略。

//映射单向 1-n 的关联关系//使用 @OneToMany 来映射 1-n 的关联关系//使用 @JoinColumn 来映射外键列的名称//可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略//可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略. //注意: 若在 1 的一端的 @OneToMany 中使用 mappedBy 属性, 则 @OneToMany 端就不能再使用 @JoinColumn 属性了.     @JoinColumn(name="CUSTOMER_ID")    @OneToMany(fetch=FetchType.EAGER)//@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.REMOVE},mappedBy="customer")public Set<Order> getOrders() {return orders;}



删除

//默认情况下, 若删除 1 的一端, 则会先把关联的 n 的一端的外键置空, 然后进行删除. //可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略. @Testpublic void testOneToManyRemove(){Customer customer = entityManager.find(Customer.class, 8);entityManager.remove(customer);}

在多对一的时候,这样子删除会因为外键约束而抛出异常,但是一对多有一些不同。

可以看到,它是将USER_ID字段置为空。但是这显然不是我们想要的。
其实我们可以使用cascade属性改变策略,比如改为级联删除。
//映射单向 1-n 的关联关系//使用 @OneToMany 来映射 1-n 的关联关系//使用 @JoinColumn 来映射外键列的名称//可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略//可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略. //注意: 若在 1 的一端的 @OneToMany 中使用 mappedBy 属性, 则 @OneToMany 端就不能再使用 @JoinColumn 属性了.     @JoinColumn(name="CUSTOMER_ID")    @OneToMany(fetch=FetchType.EAGER,cascade={CascadeType.REMOVE})//@OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.REMOVE},mappedBy="customer")public Set<Order> getOrders() {return orders;}

//默认情况下, 若删除 1 的一端, 则会先把关联的 n 的一端的外键置空, 然后进行删除. //可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略. @Testpublic void testOneToManyRemove(){Customer customer = entityManager.find(Customer.class, 8);entityManager.remove(customer);}



修改

//默认情况下, 若删除 1 的一端, 则会先把关联的 n 的一端的外键置空, 然后进行删除. //可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略. @Testpublic void testOneToManyRemove(){Customer customer = entityManager.find(Customer.class, 6);entityManager.remove(customer);}


======

1 0
原创粉丝点击