关闭

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

标签: hibernate映射文件一对多双向关联客户和订单hibernate-mapping
1108人阅读 评论(0) 收藏 举报
分类:

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

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>












0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:392786次
    • 积分:6724
    • 等级:
    • 排名:第3661名
    • 原创:280篇
    • 转载:17篇
    • 译文:0篇
    • 评论:86条
    博客专栏
    最新评论