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>












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

【hibernate】一对多(客户与订单双向关联)遇到的异常

1)报错原因:创建Configuration对象没有调用configure()方法,意味着没有加载hibernante.cfg.xml映射文件。 解决办法:创建Configuration对象的同时,要...

面向对象之封装,继承,多态

Java是一种面向对象的语言,这是大家都知道的,他与那些像c语言等面向过程语言不同的是它本身所具有的面向对象的特性——封装,继承,多态,这也就是传说中的面向对象三大特性...

重新认识java(四) — 组合、聚合与继承的爱恨情仇

有人学了继承,认为他是面向对象特点之一,就在所有能用到继承的地方使用继承,而不考虑究竟该不该使用,无疑,这是错误的。那么,究竟该如何使用继承呢?...

Hibernate 中annotations(注解开发)的@OneToMany 一对多双向关联映射后,出现的jar包冲突问题

Hibernate 注解开发时,一对多关系映射时发生了jar包冲突问题,java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanR...
  • Elenal
  • Elenal
  • 2016年08月23日 20:28
  • 996

Hibernate从入门到精通(九)一对多双向关联映射

上次的博文Hibernate从入门到精通(八)一对多单向关联映射中,我们讲解了一下一对多单向映射的相关内容,这次我们讲解一下一对多双向映射的相关内容。...

Hibernate一对多双向关联映射

Department部门和Employee员工是一对多的关系,再多的一端会有一个外键来

Hibernate一对多单向关联和双向关联映射方法及其优缺点

一对多关联映射和多对一关联映射实现的基本原理都是一样的,既是在多的一端加入一个外键指向一的一端外键,而主要的区别就是维护端不同。 它们的区别在于维护的关系不同: 一对多关联映射是指在加...

Hibernate一对多单向关联和双向关联映射方法及其优缺点

一对多关联映射和多对一关联映射实现的基本原理都是一样的,既是在多的一端加入一个外键指向一的一端外键,而主要的区别就是维护端不同。 它们的区别在于维护的关系不同: 一对多关联映射是指在加...

Hibernate一对多单向关联和双向关联映射方法及其优缺点

Hibernate一对多单向关联和双向关联映射方法及其优缺点 本文由arthinking发表于3年前 | J2EE | 暂无评论 |  被围观 5,750 views+ 一对多关...

Hibernate映射详解(二)--多对一,一对多单向,一对多双向关联映射

在我们以前的数据库设计中,设计表就不是一件轻松的事情。多种事物之间往往都是有这样那样的关系的。那怎样设计表格,才能既将事情描述明白,又能使数据库设计的比较合理呢?那里我们提供了好多规范,好多约束来满足...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hibernate的一对多双向关联映射----客户和订单关系
举报原因:
原因补充:

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