Hibernate双向一对多级联保存优化

本文讨论:在Hibernate双向一对多级联保存中,SQL条数过多的问题

 1、建立表结构

use `hibernate-orm`;
drop table if exists `orders`;
drop table if exists `Customer`;
/* 客户表(单方) */
create table `Customer`
(
 id int primary key auto_increment,
 name varchar(50) comment '客户姓名',
 age int comment '客户年龄'
);
/* 订单表(多方) */
create table `orders`
(
 id int primary key auto_increment,
 name varchar(50) comment '订单名称',
 orderno int comment '订单号',
 customer_id int comment '所属的客户',
 constraint foreign key(`customer_id`) references `Customer`(`id`)
);
select * from `orders`;
select * from `customer`;

2、建立Customer实体对象

package dai.hao.hibernate.one2many.ano._double;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
 * 客户类,单方
 *
 * @author Horace <br/>
 *
 * 2014年8月27日 下午9:08:36
 */
@Entity
@Table(name = "Customer")
public class Customer
{
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private int id;
 private String name;
 private int age;
 // 设置关联关系
 @OneToMany(targetEntity = Order.class, cascade = CascadeType.ALL)
 // name指定对方表的外键字段
 @JoinColumn(name = "customer_id")
 private Set<Order> orders;
 public Set<Order> getOrders()
 {
  return orders;
 }
 public void setOrders(Set<Order> orders)
 {
  this.orders = orders;
 }
 public Customer()
 {
 }
 public Customer(String name, int age)
 {
  super();
  this.name = name;
  this.age = age;
 }
 public int getId()
 {
  return id;
 }
 public void setId(int id)
 {
  this.id = id;
 }
 public String getName()
 {
  return name;
 }
 public void setName(String name)
 {
  this.name = name;
 }
 public int getAge()
 {
  return age;
 }
 public void setAge(int age)
 {
  this.age = age;
 }
 @Override
 public String toString()
 {
  return "Customer [id=" + id + ", name=" + name + ", age=" + age + "]";
 }
}

3、建立Order实体对象

package dai.hao.hibernate.one2many.ano._double;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
 * 订单类,多方
 *
 * @author Horace <br/>
 *
 * 2014年8月27日 下午9:09:41
 */
@Entity
@Table(name = "orders")
public class Order
{
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private int id;
 private String name;
 private int orderno;
 @ManyToOne(targetEntity = Customer.class, cascade = CascadeType.ALL)
 @JoinColumn(name = "customer_id")
 private Customer customer;
 public Customer getCustomer()
 {
  return customer;
 }
 public void setCustomer(Customer customer)
 {
  this.customer = customer;
 }
 public Order()
 {
 }
 public Order(String name, int orderno)
 {
  super();
  this.name = name;
  this.orderno = orderno;
 }
 public int getId()
 {
  return id;
 }
 public void setId(int id)
 {
  this.id = id;
 }
 public String getName()
 {
  return name;
 }
 public void setName(String name)
 {
  this.name = name;
 }
 public int getOrderno()
 {
  return orderno;
 }
 public void setOrderno(int orderno)
 {
  this.orderno = orderno;
 }
 @Override
 public String toString()
 {
  return "Order [id=" + id + ", name=" + name + ", orderno=" + orderno + "]";
 }
}
4、不需要额外的映射关系的配置文件
5、执行测试
package dai.hao.hibernate.one2many.ano._double;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
public class Main
{
 @Test
 public void testCascadeAdd()
 {
  // 保存客户级联保存订单
 
  Session session = HiberUtils.getCurrentSession();
  Transaction transaction = session.getTransaction();
  transaction.begin();
 
  Customer customer = new Customer("Horace", 22);
  Order order1 = new Order("订单1", 123456);
  Order order2 = new Order("订单2", 234567);
  Set<Order> orders = new HashSet<Order>();
  orders.add(order1);
  orders.add(order2);
  customer.setOrders(orders);
  session.save(customer);
 
  transaction.commit();
  HiberUtils.close();
 
 }
}

6、执行结果(双方都维护关联关系的情况下,可以发现多了两条SQL)

Hibernate: insert into Customer (age, name) values (?, ?)
Hibernate: insert into orders (customer_id, name, orderno) values (?, ?, ?)
Hibernate: insert into orders (customer_id, name, orderno) values (?, ?, ?)
Hibernate: update orders set customer_id=? where id=?
Hibernate: update orders set customer_id=? where id=?

 7、修改Customer实体对象,让多方(Order)维护关联关系

package dai.hao.hibernate.one2many.ano._double;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
 * 客户类,单方
 *
 * @author Horace <br/>
 *
 * 2014年8月27日 下午9:08:36
 */
@Entity
@Table(name = "Customer")
public class Customer
{
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private int id;
 private String name;
 private int age;
 // 设置关联关系
 /*
  * 在双向关联关系中,mappedBy属性表示由对方维护关联关系,其属性值是对方实体中本方的类属姓名
  * 如:private Customer customer;
  * 相当于xml配置中的inverse="true"。
  * 此时需要注意的是不要写@JoinColumn,因为在本方已经不需要维护关联关系了
  */
 
 @OneToMany(mappedBy="customer", cascade = CascadeType.ALL)
 private Set<Order> orders;
 public Set<Order> getOrders()
 {
  return orders;
 }
 public void setOrders(Set<Order> orders)
 {
  this.orders = orders;
 }
 public Customer()
 {
 }
 public Customer(String name, int age)
 {
  super();
  this.name = name;
  this.age = age;
 }
 public int getId()
 {
  return id;
 }
 public void setId(int id)
 {
  this.id = id;
 }
 public String getName()
 {
  return name;
 }
 public void setName(String name)
 {
  this.name = name;
 }
 public int getAge()
 {
  return age;
 }
 public void setAge(int age)
 {
  this.age = age;
 }
 @Override
 public String toString()
 {
  return "Customer [id=" + id + ", name=" + name + ", age=" + age + "]";
 }
}

8、测试–注意:测试用例有修改

package dai.hao.hibernate.one2many.ano._double;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
public class Main
{
 @Test
 public void testCascadeAdd()
 {
  // 保存客户级联保存订单
  Session session = HiberUtils.getCurrentSession();
  Transaction transaction = session.getTransaction();
  transaction.begin();
  /**
   * 特别注意: 因为mappedBy是定义在customer中,即Customer类不负责维护级联关系.即维护者是Order.所以,
   * 要将Customer的数据,赋给Order,即用Order的setCustomer()方法去捆定Customer数据;
   */
  Customer customer = new Customer("Horace", 22);
  Order order1 = new Order("订单1", 123456);
  Order order2 = new Order("订单2", 234567);
  Set<Order> orders = new HashSet<Order>();
  orders.add(order1);
  orders.add(order2);
  customer.setOrders(orders);
  order1.setCustomer(customer);
  order2.setCustomer(customer);
  session.save(customer);
  transaction.commit();
  HiberUtils.close();
 }
}

9、执行结果

Hibernate: insert into Customer (age, name) values (?, ?)
Hibernate: insert into orders (customer_id, name, orderno) values (?, ?, ?)
Hibernate: insert into orders (customer_id, name, orderno) values (?, ?, ?)

总结:在双向关联关系中,需要设置xml–>inverse=”true”,注解:mappedBy=”对方实体中本方属性名”,把关联关系交给多方表控制,那么会省去不必要的SQL,达到优化的效果。

posted @ 2015-03-25 12:03  贺瑞斯  阅读(501)  评论(0编辑  收藏  举报