2010年9月9日 星期四

Hibernate 教學 - 多對多

這篇要來介紹一下在 Hibernate 中的多對多關聯

設計模式通常是採用仲介 Table 的方式來聯繫其他兩個個體間的關係

所以通常須設計三個 Table 來實現資料庫的多對多關係

在物件和物件中,盡量避免設計出多對多的關聯

我也有點同感,的確多對多關係是有那嚜一點沒必要

但是既然物件和物件有這樣的關聯那就必須去理解了

接下來說明的是多對多關聯(雙向),雙向就是彼此都認得彼此。














以上是ㄧ個多對多的資料表關聯圖

ㄧ個 Course 會對應到好幾個Learner,而一個 Learner 又會有好幾個 Course

來看一下這兩個類別如何設計:

Course class :
package MapPOJO;
import java.util.Set;
public class Course implements java.io.Serializable
{
    private Long id;
    private String name;
    private Set learners;  //一個 Course 會有好幾個 Learner

    public Course(){}

    public Long getId(){
        return id;
    }
    public void setId(Long id){
        this.id = id;
    }
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
    public Set getLearners(){
        return learners;
    }
    public void setLearners(Set learners){
        this.learners = learners;
    }
}
Learner class :
package MapPOJO;
import java.util.Set;
public class Learner implements java.io.Serializable
{
    private Long id;
    private String name;
    private Set courses;  //一個 Learner 會有好幾個 Course

    public Learner(){}

    public Long getId(){
        return id;
    }
    public void setId(Long id){
        this.id = id;
    }
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
    public Set getCourses(){
        return courses;
    }
    public void setCourses(Set courses){
        this.courses = courses;
    }
}

基本上上述的兩個類別並不難,都是以一對多為基礎

形成一個多對多的關係,使得 Course 可以取出 Learner,而 Learner 也可以取出 Course

再來看看組態檔的設定

Course.hgm.xml :



  
      
          
      
      

      
      
          
          

          
          
                   
      
  

Learner.hbm.xml :



  
      
          
      
      
      
      
          
            
      
  


接下來再用 JSP 模擬一些資料的儲存

// JSP省略部份...
    Learner l1 = new Learner();
    l1.setName("Allen");
    Learner l2 = new Learner();
    l2.setName("Nico");

    Course c1 = new Course();
    c1.setName("programming");
    Course c2 = new Course();
    c2.setName("English");

    Set hs = new HashSet();
    hs.add(l1);
    hs.add(l2);
    c1.setLearners(hs);  //讓 Learner 和 Course 產生關聯, Course 可取出 Learner
    c2.setLearners(hs);  //讓 Learner 和 Course 產生關聯, Course 可取出 Learner

    Set s = new HashSet();
    s.add(c1);
    s.add(c2);
    l1.setCourses(s);  //讓 Course 和 Learner 產生關聯, Learner可取出 Course 
    l2.setCourses(s);  //讓 Course 和 Learner 產生關聯, Learner可取出 Course 

    org.hibernate.SessionFactory sessionfactory = HibernateUtil.getSessionFactory();
    org.hibernate.Session session1 = sessionfactory.openSession();
    org.hibernate.Transaction tx = session1.beginTransaction();

    session1.save(l1); //因為現在維護物件的主控權在 Learner 身上,所以save Learner 即可
    session1.save(l2);

    tx.commit();
    session1.close();
// JSP省略部份...


最後再補充說明幾點

首先在 仲介Table 中的 course_fkid、learner_fkid,是主鍵

在前面的圖忘記加上去了, 但可別把他們設定為 auto_increasment 喔

再來就是一開始我再寫多對多的時候,真的去設定他們兩個為外鍵

結果產生了以下的錯誤

org.apache.catalina.loader.WebappClassLoader loadClass
資訊: Illegal access: this web application instance has been stopped already. Could not load com.mysql.jdbc.profiler.ProfilerEventHandlerFactory. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException

如果出同樣的錯,可以試試看是不是這樣的問題。

沒有留言:

張貼留言