2月4日——培训第63天

 三元关系的另外两种处理方式:

帮助手册中的chapter6中Advanced collectionMapping中的Ternary associations
就是讲解三元关系处理的。

1 使用Map,让关系成为其索引。(仅能单纯的映射三元关系)

2 将一个关系重构为实体类,这是我们应用的最多的

3 使用组成

例1:

配置文件:

          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

 
    org.hibernate.dialect.MySQLDialect
   
    com.mysql.jdbc.Driver
    jdbc:mysql:///struts
    root
    root
   
    true
    true
   
    thread
 

 

classroom、course和user三个表

关系表classroom_tea_course:

字段:
tea_id:    INTEGER
class_id:  INTEGER
course_id: INTEGER

以上三个每一个都是外键,都对应着一个表

package cn.itcast.vo;

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

public class Teacher {
 private int id;

 private String empNo;

 private Float salary;

}

----------------------------------------
package cn.itcast.vo;

public class Course {
 private int id;

 private String courseName;

 public boolean equals(Object obj) {
  // TODO Auto-generated method stub
  if(obj==null) return false;
  if(obj==this) return true;
  
  if(obj instanceof Course) {
   Course c = (Course) obj;
   if(c.getId()==id) return true;
  }
  return false;
 }

 public int hashCode() {
  // TODO Auto-generated method stub
  return id;
 }
}

------------------------------------------
package cn.itcast.vo;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Classroom {
 private int id;

 private String location;

 private int maxSeat;
 
 private Map teacherCourses = new HashMap();
}
--------------------------------------------



          "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

 
  
   
  

  
  

 

 
  
   
  

  
 

 
  
   
  

  
  
  
   
    //
   
   
    //用classroom_tea_course的外键对Course的主键。
  

 

//键是老师,值是Course,教室号是外键

 


public class Demo
{
 public static void main(String[] args)
 {
  SessionFactory factory = new Configuration()
    .addResource("cn/itcast/vo/User.hbm.xml")
    .configure()
    .buildSessionFactory() ;
  //由于工程里面的实体类中没有User,所以这里必须用addResource!
  Session session = factory.getCurrentSession() ;
  session.beginTransaction() ;
  
  
  Teacher t = (Teacher)session.get(Teacher.class,new Integer(1));
  Course c = (Course)session.get(Course.class,new Integer(1));
  Classroom cr = (Classroom)session.get(Classroom.class,new Integer(1));
  cr.getTeacherCourses().put(t,c);
  //三个实体都是通过get方法加载进来的,所以都处于持久状态……
  
  cr.getTeacherCourses().put(t,new Course().setId(2));
  //由于是map,所以上面这句话将会覆盖上面的c……其实说白了teacher和classroom由于
  //在map里面是键值对的关系,所以teacher和classroom必须是一对一或是多对一的关系,这就对
  //多元关系造成了一定的局限……………………所以这种方法几乎不太用。(key和value必须是一对一或是多对一
  //但是绝对不可以是一对多,否则绝对会出现覆盖现象)
  session.getTransaction().commit() ;
  session.close() ;
  factory.close() ;
 }
}

三者之间的关系:Teacher和Course:一对一或多对一,Teacher对的Course永远只有一个。但是也可以让
一个老师对应多门课程,通过重载equals方法的方式、让key以某种方式和上一个不一样就可以了。

教室和老师课程的实体map之间是多对多关系。

其实由于一门课程只能在一个教室里面上,一个教室可以上多门课程,所以最好应该让Classroom和Course之间
组成map,而且要让课程为key,教室为value;
----------------------------------------------------------------------------------------

 


 
 
 

以上应用在没有关系表的情况下,
要求在Contract中必须有外键employer_id和employee_id,
即one-to-many对应的表中有key和map-key-many-to-many所声明的外键


 
 
 

以上应用在有关系表的情况下,
但map-key-many-to-many和many-to-many之间只能是多对一的关系。

==========================================================================
==========================================================================
下午课程开始:

组成:

组成代表了对象间不可分割的联系,成员与整体共存亡。
使用组成可以提高代码的可重用性,降低维护难度,并且易于理解。
例如:人和姓名之间就是组成关系,如果人不存在了其姓名也就没有存在的价值了。

Person:id、name(Name)、age、gender、birthday
Name:firstName、lastName

Person中持有Name的实体,在数据表中把两个实体映射到一张表中去:
person表:person_id first_name last_name age gender birthday

映射文件:


   
      
   

   
   
   
   
      //指明谁拥有name
     
     
   

 

写两个类,一个Person,一个Name,然后Name中持有一个owner,指明谁
拥有这个名字。

Name name = new Name();
name.setFirstName("bill");
name.setLastName("gates");

Person p = new Person();
p.setName(name);

session.save(p);

有些时候组成整体的部分并非仅有一个,如一栋楼由多个单元组成,一个单
元由多个房间组成,一个房间又由多个室组成。
在组成成为集合时,必须由独立的表存储组成的成员,然后通过主外键关系
组成成员。需要指明组成外键。
在使用上与一对多的关系相差无几。
----------------------------------------------------------
再来考虑订单和订单项之间的关系

订单Orders有属性id、name、date和items
订单项Lineitem中有属性lineNumber、order、quantity、price

Orders和Lineitem之间是一对多的关系。

orders表:order_id、order_name、order_date
line_items表:item_number、order_id、quantity、price

映射文件:


   
      
   

   
   
   
      
      
        
        
        
      

   

 

 

动态组成以Map表示组成成员,key为属性名,value为属性值:

    
    
    

=============================================================

映射三元关系的第三种方式:组成方式。

其中第一种Map还有另外一种不使用关系表的方式,详见手册的6.3.4节。





//没有关系表





//有关系表

-------------------------------------------------------
手册的第8章节Component Mapping里面就是说的这种组合方式解决三元关系,
也是对关系重构的一种方式。


....







联合主键:8.4节:

       class="ClassName"
       mapped=“true|false” 
       access="field|property|ClassName">
         type="typename"
        column="column_name"/>
           column="column_name"/>
......

对于使用联合主键的POJO对象必须要重载equals方法和hashCode方法



注意事项:

You may use a component as an identifier of an entity class. Your component
class must satisfy certain requirements:

It must implement java.io.Serializable.
It must re-implement equals() and hashCode(), consistently with the database's
notion of composite key equality.

类必须实现Serializable接口并且要重载equals和hashCode方法,但是对于Hibernate3来说,
第二个要求并不是必须的,但是你最好还是重载它。


-------------------------------------------------------------------------------

下面拿订单和订单项来举例,联合主键是订单号和订单项的号联合起来作为主键。

先不做成组成的关系,让订单和订单项先映射成各自独立的实体。

Order里面持有一个Set,Set里面都是订单项,然后LineItem中持有一个Order实体对象。

写一个类继承自Serializable接口


弓燕军写的配置文件:


 
   org.hibernate.dialect.MySQLDialect
   com.mysql.jdbc.Driver
   jdbc:mysql:///netstore?useUnicode=true&
        characterEncoding=gbk

   root
   1234
   
   true
   true
   thread
   
   
 


---------------------------------------------------------------------------


 
  
   
  

  
   
  

  
   
   
  

 

 
 
  
   
   
  

  
   
 


------------------------------------------------------------------------------
订单的实体类:

public class Order implements Serializable{
 /**
  *
  */
 private static final long serialVersionUID = 0;
 private int id;
 private String orderNumber;
 private int item_id;
 private Set lineItems = new HashSet();

 public boolean equals(Object obj) {
  if(obj == null)
   return false;
  if(obj == this)
   return true;
  if(obj instanceof Order)
  {
   Order o = (Order)obj;
   if(o.getId() == id)
   {
    return true;
   }
  }
  return false;
 }
 
 public int hashCode() {
  return id;
 }

}


订单项:

public class LineItem {
 private CompositeKey key;
 private double base_price;
 private int quantity;
}


联合主键也需要一个类:

public class CompositeKey implements Serializable{
 
 private static final long serialVersionUID = 0;
 private Order order;
 private int item_id;
 
 public int getItem_id() {
  return item_id;
 }
 public void setItem_id(int item_id) {
  this.item_id = item_id;
 }
 public Order getOrder() {
  return order;
 }
 public void setOrder(Order order) {
  this.order = order;
 }
 @Override
 public boolean equals(Object obj) {
  if(obj == null)
   return false;
  if(obj == this)
   return true;
  if(!(obj instanceof CompositeKey))
   return false;
  CompositeKey c = (CompositeKey)obj;
  if(!c.getOrder().equals(order))
   return false;
  if(c.getItem_id() != item_id)
   return false;
 
  return true;
  
 }
 @Override
 public int hashCode() {
  return order.getId() + item_id;
 }
 
 
 
}

-----------------------------------------

测试类:

public class Demo {

 /**
  * @param args
  */
 public static void main(String[] args) {
  SessionFactory factory = new Configuration().configure().buildSessionFactory();
  Session session = null;
  
  try {
   session = factory.getCurrentSession();
   session.beginTransaction();
   Order order = new Order();
   order.setOrderNumber("111111");
   session.save(order);
   CompositeKey key = new CompositeKey();
   key.setOrder(order);
   LineItem item1 = new LineItem();
   item1.setKey(key);
   item1.setBase_price(20.5);
   item1.setQuantity(5);
   LineItem item2 = new LineItem();
   item2.setKey(key);
   item2.setBase_price(80.9);
   item2.setQuantity(10);
   session.save(item1);
   session.save(item2);
   session.getTransaction().commit();
  } catch (HibernateException e) {
   if(session != null && session.getTransaction() != null)
   {
    session.getTransaction().rollback();
   }
   e.printStackTrace();
  }finally{
   if(session != null)
   {
    session.close();
    session = null;
   }
  }
  factory.close();

 }

}

你可能感兴趣的:(四个月的编程培训经历)