hibernate的一对多双向关联映射----客户和订单关系

原创 2015年11月18日 20:58:40

客户和订单关系:客户是一的一方,订单是多的一方。

customer表:


CREATE TABLE `customer` (
`ID`  int(4) NOT NULL AUTO_INCREMENT ,
`CNAME`  char(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`BANK`  varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`PHONE`  varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
PRIMARY KEY (`ID`)
)
orders表:


CUSTOMER_ID是外键!


CREATE TABLE `orders` (
`ID`  int(4) NOT NULL AUTO_INCREMENT ,
`ORDERNO`  varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
`MONEY`  double(10,2) NULL DEFAULT NULL ,
`CUSTOMER_ID`  int(4) NULL DEFAULT NULL ,
PRIMARY KEY (`ID`),
FOREIGN KEY (`CUSTOMER_ID`) REFERENCES `customer` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE,
INDEX `CUSTOMER_ID` (`CUSTOMER_ID`) USING BTREE 
)
PO对象

Customer.java

package com.PO;

import java.util.HashSet;
import java.util.Set;

/**
 * Company entity. @author tuke
 */

public class Customer  implements java.io.Serializable {  
     private Integer id;      
     private String cname;     //客户名称
     private String bank;      //银行账号
     private String phone;     //电话号码
     
     private Set<Orders> orderses = new HashSet<Orders>();  //关联另外一个类

    // Constructors
    /** default constructor */
    public Customer() {
    }
   
    /** full constructor */
    public Customer(String cname, String bank, String phone, Set<Orders> orderses) {
        this.cname = cname;
        this.bank = bank;
        this.phone = phone;
        this.orderses = orderses;
    }

    // Property accessors

    public Integer getId() {
        return this.id;
    }   
    public void setId(Integer id) {
        this.id = id;
    }
    public String getCname() {
        return this.cname;
    }    
    public void setCname(String cname) {
        this.cname = cname;
    }

    public String getBank() {
        return this.bank;
    }
    
    public void setBank(String bank) {
        this.bank = bank;
    }

    public String getPhone() {
        return this.phone;
    }
    
    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Set<Orders> getOrderses() {
        return this.orderses;
    }
    
    public void setOrderses(Set<Orders> orderses) {
        this.orderses = orderses;
    }
  
}
Customer.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.PO.Customer" table="customer" catalog="onetomany">
        <id name="id" type="integer">
            <column name="ID" />
            <generator class="identity"></generator>
        </id>
        <property name="cname" column="CNAME" type="string"></property>
        <property name="bank"  column="BANK" type="string"> </property>      
        <property name="phone" column="PHONE" type="string"> </property>
       
        <!-- 一对多双向映射customer到orders,单的一方配置 ,name是PO类Company的属性,table是关联表名,如果设置成inverse为true,以设定一方到多方的设定是逆向映射,即可以从多放引导到一方。一定要加lazy="false"否则会出现延迟加载错误-->
        <set name="orderses" table="orders" inverse="true"  lazy="false" cascade="all" >
            <key column="CUSTOMER_ID"/><!--外键字段: <key>标签指定的外键字段必须和<many-to-one>指定的外键字段一致 -->
            <one-to-many class="com.PO.Orders" /><!-- 用关联表对应的PO类实例做value值 -->
        </set>
        
    </class>
</hibernate-mapping>
Orders.java

package com.PO;

/**
 * Orders entity. @author tuke
 */

public class Orders  implements java.io.Serializable {
  
     private Integer id;   
     private String orderno;
     private double money;
          
     private Customer customer;//关联customer
    /** default constructor */
    public Orders() {
    }
   
    /** full constructor */
    public Orders(Customer customer, String orderno, double money) {
        this.customer = customer;
        this.orderno = orderno;
        this.money = money;
    }
  
    // Property accessors
    public Integer getId() {
        return this.id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }

    public Customer getCompany() {
        return this.customer;
    }
    
    public void setCompany(Customer customer) {
        this.customer = customer;
    }

    public String getOrderno() {
        return this.orderno;
    }
    
    public void setOrderno(String orderno) {
        this.orderno = orderno;
    }

    public double getMoney() {
        return this.money;
    }
    
    public void setMoney(double money) {
        this.money = money;
    }


	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
   
}
Orders.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.PO.Orders" table="orders" catalog="onetomany">
        <id name="id" type="integer">
            <column name="ID" />
            <generator class="identity"></generator>
        </id>
        <property name="orderno" column="ORDERNO" type="string"> </property>
        <property name="money"   column="MONEY" type="double"> </property>
       
        <!-- 一对多双向关联映射中,多的一方配置manytoone ,name是PO属性,一定要加lazy="false"否则会出现延迟加载错误-->
        <many-to-one name="customer" column="CUSTOMER_ID"  class="com.PO.Customer" lazy="false">
        </many-to-one>
    </class>
</hibernate-mapping>
TestBean.java

package com.test;

import java.util.Random;

import com.PO.Customer;
import com.PO.Orders;
import com.dao.OneManyDao;

public class TestBean {
      OneManyDao dao=new OneManyDao();
      Random rnd=new Random();
      public void addCustomer(){
    	  Customer customer=new Customer();
    	
    	  customer.setCname("tuke");
    	  customer.setBank("中国银行");
    	  customer.setPhone("027-12121221");
    	  //数据库操作
    	  dao.addCustomer(customer);
      }
      
      public Customer loadCustomer(Integer id){
    	  return dao.loadCustomer(id);
      }
      //为客户customer添加订单orders,被控方操作
      public void addOrders(Customer customer){
    	    //随机生成order对象
    	    Orders order=new Orders();
    	   
    	    order.setOrderno(new Integer(rnd.nextInt()*10000).toString());
            order.setMoney(new Double(rnd.nextDouble()*10000));
            order.setCustomer(customer);//如果映射文件正确,则orders表的CUSTOMER_ID字段会有customer的ID
            
            //把生成的order对象,加入customer的set集合中
            customer.getOrderses().add(order);
            System.out.println( customer.getOrderses().contains(order));
            dao.addOrders(order);
      }
     public Orders loadOrders(Integer id){
    	 return dao.loadOrders(id);
     }     
}
OneManyDao.java

package com.dao;

import org.hibernate.Session;
import org.hibernate.Transaction;

import SessionFactory.HibernateSessionFactory;

import com.PO.Customer;
import com.PO.Orders;

/**
 * Data access object (DAO) for domain model
 * @author tuke
 */
public class OneManyDao {
	     //添加客户信息
	   public void addCustomer(Customer customer){
		    Session session=HibernateSessionFactory.getSession();
		    Transaction ts=null;
		    try{
		    	ts=session.beginTransaction();
		        //保存customer对象的同时,会保存其包含的所有订单
		    	session.saveOrUpdate(customer);
		    	ts.commit();
		    }catch(Exception ex){
		    	ts.rollback();
		    	System.out.println("添加客户失败!");
		    }finally{
		    	HibernateSessionFactory.closeSession();
		    }
	   }
	   //加载客户信息
	   public Customer loadCustomer(Integer id){
		   Session session=HibernateSessionFactory.getSession();
		    Transaction ts=null;
		    Customer customer=null;
		    try{
		    	ts=session.beginTransaction();
		    	//加载customer信息时,同样会加载其所有的订单信息
		    	customer=(Customer)session.get(Customer.class, id);
		    	ts.commit();
		    }catch(Exception ex){
		    	ts.rollback();
		    	System.out.println("获取客户失败!");
		    }finally{
		    	HibernateSessionFactory.closeSession();
		    }
		    return customer;
	   }
	   //添加订单信息
	   public void addOrders(Orders order){
		   Session session=HibernateSessionFactory.getSession();
		    Transaction ts=null;
		    try{
		    	ts=session.beginTransaction();
		    	session.save(order);
		    	ts.commit();
		    }catch(Exception ex){
		    	ts.rollback();
		    	System.out.println("添加订单失败!");
		    }finally{
		    	HibernateSessionFactory.closeSession();
		    }
		 
	   }
	   //加载订单信息
	   public Orders loadOrders(Integer id){
		   Session session=HibernateSessionFactory.getSession();
		    Transaction ts=null;
		    Orders order=null;
		    try{
		    	ts=session.beginTransaction();
		    	order=(Orders)session.get(Orders.class, id);
		    	ts.commit();
		    }catch(Exception ex){
		    	ts.rollback();
		    	System.out.println("获取订单失败!");
		    }finally{
		    	HibernateSessionFactory.closeSession();
		    }
		    return order;
	   }
	  	
}
测试页面test.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="com.PO.*" import="com.test.*" import="java.text.NumberFormat"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>hibernate的一对多双向关联关系映射</title>
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
  </head>
  
  <body> 
     <h2>hibernate的一对多双向关联关系映射</h2>
     <hr>
     <jsp:useBean id="test" class="com.test.TestBean"></jsp:useBean>
     <%
       test.addCustomer();
       Integer id=new Integer(1);
       Customer customer=test.loadCustomer(id);
       //给该客户增加三个订单
       test.addOrders(customer);
       test.addOrders(customer);
       test.addOrders(customer);
       
       //根据指定的客户,得到该客户的所有订单  
      NumberFormat nf=NumberFormat.getCurrencyInstance();
      out.println("<br>客户"+customer.getCname()+"的所有订单");
      Iterator<Orders> it=customer.getOrderses().iterator();
       Orders order=null;
       while(it.hasNext()){
            order=(Orders)it.next();
            System.out.println(order.getOrderno());
            out.println("<br>订单号:"+order.getOrderno());
            out.println("<br>订单金额:"+nf.format(order.getMoney()));
       }
       
     //根据指定的订单,得到其所属的客户
     order=test.loadOrders(new Integer(28));
     customer=order.getCustomer();
     out.println("<br>");
     out.println("<br>订单号为:"+order.getOrderno().trim()+"的所属客户为:"+customer.getCname());
        
     %>
  </body>
</html>
测试结果:






控制台打印的sql语句是:

Hibernate: 
    insert 
    into
        onetomany.customer
        (CNAME, BANK, PHONE) 
    values
        (?, ?, ?)
Hibernate: 
    select
        customer0_.ID as ID1_0_,
        customer0_.CNAME as CNAME1_0_,
        customer0_.BANK as BANK1_0_,
        customer0_.PHONE as PHONE1_0_ 
    from
        onetomany.customer customer0_ 
    where
        customer0_.ID=?                           //上面是save和load一个customer
Hibernate: 
    select
        orderses0_.CUSTOMER_ID as CUSTOMER4_1_,
        orderses0_.ID as ID1_,
        orderses0_.ID as ID0_0_,
        orderses0_.ORDERNO as ORDERNO0_0_,
        orderses0_.MONEY as MONEY0_0_,
        orderses0_.CUSTOMER_ID as CUSTOMER4_0_0_ 
    from
        onetomany.orders orderses0_ 
    where
        orderses0_.CUSTOMER_ID=?
true
Hibernate: 
    insert 
    into
        onetomany.orders
        (ORDERNO, MONEY, CUSTOMER_ID) 
    values
        (?, ?, ?)
true
Hibernate: 
    insert 
    into
        onetomany.orders
        (ORDERNO, MONEY, CUSTOMER_ID) 
    values
        (?, ?, ?)
true
Hibernate: 
    insert 
    into
        onetomany.orders
        (ORDERNO, MONEY, CUSTOMER_ID) 
    values
        (?, ?, ?)    //上面是给客户添加三个订单的sql                                                
741563392
-1674530192
-635127520       //这是三个customer实例中set集合里的三个订单号
Hibernate: 
    select
        orders0_.ID as ID0_0_,
        orders0_.ORDERNO as ORDERNO0_0_,
        orders0_.MONEY as MONEY0_0_,
        orders0_.CUSTOMER_ID as CUSTOMER4_0_0_ 
    from
        onetomany.orders orders0_ 
    where
        orders0_.ID=?
Hibernate: 
    select
        customer0_.ID as ID1_0_,
        customer0_.CNAME as CNAME1_0_,
        customer0_.BANK as BANK1_0_,
        customer0_.PHONE as PHONE1_0_ 
    from
        onetomany.customer customer0_ 
    where
        customer0_.ID=?
Hibernate: 
    select
        orderses0_.CUSTOMER_ID as CUSTOMER4_1_,
        orderses0_.ID as ID1_,
        orderses0_.ID as ID0_0_,
        orderses0_.ORDERNO as ORDERNO0_0_,
        orderses0_.MONEY as MONEY0_0_,
        orderses0_.CUSTOMER_ID as CUSTOMER4_0_0_ 
    from
        onetomany.orders orderses0_ 
    where
        orderses0_.CUSTOMER_ID=?
总结:

一对多双向关联映射:
* 在“一”一端的集合上使用<key>,<key>标签指定的是外键字段,在对方表中加入一个外键指向一一端
* 在多一端采用<many-to-one>

注意:<key>标签指定的外键字段必须和<many-to-one>指定的外键字段一致,否则引用字段的错误

关键配置代码如下:

<!-- 一对多双向映射customer到orders,单的一方配置 ,name是PO类Company的属性,table是关联表名,如果设置成inverse为true,以设定一方到多方的设定是逆向映射,即可以从多放引导到一方。一定要加lazy="false"否则会出现延迟加载错误-->
        <set name="orderses" table="orders" inverse="true"  lazy="false" cascade="all" >
            <key column="CUSTOMER_ID"/><!--外键字段: <key>标签指定的外键字段必须和<many-to-one>指定的外键字段一致 -->
            <one-to-many class="com.PO.Orders" /><!-- 用关联表对应的PO类实例做value值 -->
        </set>
 <!-- 一对多双向关联映射中,多的一方配置manytoone ,name是PO属性,一定要加lazy="false"否则会出现延迟加载错误-->
        <many-to-one name="customer" column="CUSTOMER_ID"  class="com.PO.Customer" lazy="false">
        </many-to-one>












版权声明:本文为博主原创文章,未经博主允许不得转载。

一对一对多关系与购物车、订单设计

购物车,用户,商品表这3这之间的关系 将这三者关联起来,数据库该咋设计呢? 我目前想到的方法就是,新建5个表: 用户表商品表购物车表用户商品关系表购物车商品关系表 主要字段就是: 用户表:...
  • qq_26222859
  • qq_26222859
  • 2016年06月05日 20:47
  • 8408

Hibernate_一对多双向关联(实例)

项目结构:  实体类中的属性(仅仅贴出属性) Student.java public class Student { private int id; private String n...
  • u012519664
  • u012519664
  • 2014年12月22日 09:45
  • 350

Hibernate多对多双向关联

以Student和Course为例,一个学生可以选多门课程,一门课程也可以被多个学生选取; 持久化类Student: package bean; import java.util.Set; ...
  • jialinqiang
  • jialinqiang
  • 2013年03月21日 11:49
  • 15327

Hibernate双向N-N关联

双向N-N关联需要通过连接表建立关系。 两端都需要使用@ManyToMany注解修饰。 可以两端同时使用@JoinTable注解修饰,如果同时使用必须保证指定的字段对应。 如果希望某一端放弃控制权,...
  • sweatOtt
  • sweatOtt
  • 2017年03月18日 11:06
  • 247

hibernate 双向关联(为什么不死循环)

本文是想通过例子,证明hibernate双向多对多的情况下,为什么相互依赖了,还没有死循环。 customers : orders = n : n,中间的关系表是 customers_orders_l...
  • psp0001060
  • psp0001060
  • 2015年12月30日 22:13
  • 1283

Hibernate多对一、双向关系、控制反转、级联配置

keep
  • u010060662
  • u010060662
  • 2016年05月25日 20:55
  • 1542

hibernate的一对多双向关联映射----客户和订单关系

客户和订单关系:客户是一的一方,订单是多的一方。 customer表: CREATE TABLE `customer` ( `ID` int(4) NOT NULL AUTO_INCRE...
  • tuke_tuke
  • tuke_tuke
  • 2015年11月18日 20:58
  • 1330

【MyBatis框架点滴】——MyBatis一对多查询

上篇文章说了MyBatis中的一对一查询的两种方法,这里总结一下MyBatis中一对多和多对一的查询方法。  业务还用上篇文章中的订单业务来分析,表结构如下:      如上图订单和用户的关系,一个订...
  • huyuyang6688
  • huyuyang6688
  • 2016年06月05日 11:30
  • 874

hibernate一对多关联映射——双向(非常常用)

原文地址:http://blog.sina.com.cn/s/blog_5fad23090100fct8.html 一对多关联映射通常设为双向的,关系字段设置在一的一端,而且在多的一端维护, 一、...
  • springsen
  • springsen
  • 2012年08月08日 16:32
  • 3540

【Hibernate步步为营】--(一对多映射)之双向关联

单向关联的一对多映射,在一的一端维护双向的关系这种做法虽然能实现但是存在很多缺陷,首先生成很多多余的SQL语句,因为多的一端不维护关系,只有一的一端维护,在进行操作时一的一端会发出多余的update语...
  • zhang_xinxiu
  • zhang_xinxiu
  • 2014年05月25日 14:26
  • 4331
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hibernate的一对多双向关联映射----客户和订单关系
举报原因:
原因补充:

(最多只允许输入30个字)