• 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,达到优化的效果。

  • 相关阅读:
    linux 配置Apache 、PHP
    SQL Server DML(SELECT)常见用法(二)
    SQL Server DML(UPDATE、INSERT、DELETE)常见用法(一)
    PropertyGrid—添加EventTab
    PropertyGrid—添加属性Tab
    PropertyGrid—默认属性,默认事件,属性默认值
    PropertyGrid—为复杂属性提供下拉式编辑框和弹出式编辑框
    PropertyGrid--为复杂属性提供编辑功能
    PropertyGrid--基本功能
    Intellij IDEA使用(一)项目模板类型
  • 原文地址:https://www.cnblogs.com/horace/p/Horace.html
Copyright © 2020-2023  润新知