集合Set對映一對多(使用xml檔案)


如果持久化類設定了包含實體參照的物件,則需要使用一對多關聯來對映集合(Set)元素。 我們可以通過任意一個Set集合來對映這個列表物件。

下面來看看看設定物件的持久化類。 在這種情況下,一個問題可以有很多答案,每個答案可能有自己的資訊,這就是為什麼使用set標籤元素來表示一個答案(Answer類)集合。

Set對映一對多關係範例

在這個範例中,使用Set實現一對多和多對一關係對映。以論壇中的問題和答案為例,從一個問題可獲取這個問題的所有回答(一對多),從一個問題反關聯(多對一)得到問題資訊。

建立一個名稱為: setonetomany 的Java專案,其結構如下所示 -

Java程式碼

首先,將執行程式建立表並將對應資料插入到表中,然後再從表中讀取資料。

Question.java 程式碼如下所示 -

package com.yiibai;

import java.util.Set;

public class Question {
    private int id;
    private String qname;
    private Set<Answer> answers;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getQname() {
        return qname;
    }

    public void setQname(String qname) {
        this.qname = qname;
    }

    public Set<Answer> getAnswers() {
        return answers;
    }

    public void setAnswers(Set<Answer> answers) {
        this.answers = answers;
    }

}

Answer.java 程式碼如下所示 -

package com.yiibai;

public class Answer {
    private int id;  
    private String answername;  
    private String postedBy;  
    private int qid;
    private Question question;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getAnswername() {
        return answername;
    }
    public void setAnswername(String answername) {
        this.answername = answername;
    }
    public String getPostedBy() {
        return postedBy;
    }
    public void setPostedBy(String postedBy) {
        this.postedBy = postedBy;
    }
    public int getQid() {
        return qid;
    }
    public void setQid(int qid) {
        this.qid = qid;
    }
    public Question getQuestion() {
        return question;
    }
    public void setQuestion(Question question) {
        this.question = question;
    }

    public String toString(){
        return this.answername+", postby : "+this.postedBy;
    }

}

組態檔案

一共有三個組態檔案,它們分別如下:

answer.hnm.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.yiibai.Answer" table="a1002">
        <id name="id">
            <generator class="increment"></generator>
        </id>
        <property name="answername"></property>
        <property name="postedBy"></property>
        <many-to-one name="question" class="com.yiibai.Question" fetch="select">
            <column name="qid" not-null="true" />
        </many-to-one>
    </class>

</hibernate-mapping>

question.hnm.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.yiibai.Question" table="q1002">
        <id name="id">
            <generator class="increment"></generator>
        </id>
        <property name="qname"></property>

        <set name="answers" table="a1002"
                inverse="true" lazy="true" fetch="select">
            <key>
                <column name="qid" not-null="true" />
            </key>
            <one-to-many class="com.yiibai.Answer" />
        </set>

    </class>

</hibernate-mapping>

hibernate.cfg.xml 檔案內容如下-

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>

    <session-factory>
        <property name="hbm2ddl.auto">update</property>

        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/test</property>
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <property name="show_sql">true</property>

        <mapping resource="question.hbm.xml" />
        <mapping resource="answer.hbm.xml" />
    </session-factory>

</hibernate-configuration>

執行範例

MainTest.java檔案的程式碼如下 -

package com.yiibai;

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

import org.hibernate.*;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.*;

public class MainTest {
    public static void main(String[] args) {
        // 但在5.1.0版本匯總,hibernate則採用如下新方式獲取:
        // 1. 組態型別安全的準服務註冊類,這是當前應用的單例物件,不作修改,所以宣告為final
        // 在configure("cfg/hibernate.cfg.xml")方法中,如果不指定資源路徑,預設在類路徑下尋找名為hibernate.cfg.xml的檔案
        final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
                .configure("hibernate.cfg.xml").build();
        // 2. 根據服務註冊類建立一個後設資料資源集,同時構建後設資料並生成應用一般唯一的的session工廠
        SessionFactory sessionFactory = new MetadataSources(registry)
                .buildMetadata().buildSessionFactory();

        /**** 上面是組態準備,下面開始我們的資料庫操作 ******/
        Session session = sessionFactory.openSession();// 從對談工廠獲取一個session

        // creating transaction object
        Transaction t = session.beginTransaction();

        Question question1 = new Question();
        question1.setQname("What is Java?");
        session.save(question1);

        Answer ans1 = new Answer();
        ans1.setAnswername("java is a programming language");
        ans1.setPostedBy("Ravi Su");
        ans1.setQuestion(question1);
        //question1.getAnswers().add(ans1);

        session.save(ans1);

        Answer ans2 = new Answer();
        ans2.setAnswername("java is a platform");
        ans2.setPostedBy("Sudhir Lee");
        ans2.setQuestion(question1);
        session.save(ans2);

        t.commit();
        session.close();

        System.out.println("success");
    }
}

FetchData.java檔案的程式碼如下 -

package com.yiibai;

import java.util.*;

import org.hibernate.*;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.*;

public class FetchData {
    public static void main(String[] args) {

        // 但在5.1.0版本匯總,hibernate則採用如下新方式獲取:
        // 1. 組態型別安全的準服務註冊類,這是當前應用的單例物件,不作修改,所以宣告為final
        // 在configure("cfg/hibernate.cfg.xml")方法中,如果不指定資源路徑,預設在類路徑下尋找名為hibernate.cfg.xml的檔案
        final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
                .configure("hibernate.cfg.xml").build();
        // 2. 根據服務註冊類建立一個後設資料資源集,同時構建後設資料並生成應用一般唯一的的session工廠
        SessionFactory sessionFactory = new MetadataSources(registry)
                .buildMetadata().buildSessionFactory();

        /**** 上面是組態準備,下面開始我們的資料庫操作 ******/
        Session session = sessionFactory.openSession();// 從對談工廠獲取一個session

        // creating transaction object
        Transaction t = session.beginTransaction();

        Query query = session.createQuery("from Question");
        List<Question> list = query.list();

        Iterator<Question> itr = list.iterator();
        while (itr.hasNext()) {
            Question q = itr.next();
            System.out.println("Question Name: " + q.getQname());

            // printing answers
            Set<Answer> set = q.getAnswers();
            Iterator<Answer> itr2 = set.iterator();
            while (itr2.hasNext()) {
                Answer an = (Answer)itr2.next();
                System.out.println(an.getAnswername());
            }

        }
        session.close();
        System.out.println("success");

    }
}

執行 MainTest.java得到以下結果 -

log4j:WARN No appenders could be found for logger (org.jboss.logging).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Sun Mar 26 23:33:27 CST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
Hibernate: create table a1002 (id integer not null, answername varchar(255), postedBy varchar(255), qid integer not null, primary key (id)) engine=InnoDB
Hibernate: create table q1002 (id integer not null, qname varchar(255), primary key (id)) engine=InnoDB
Hibernate: alter table a1002 add constraint FK9la7qmitcg24x22e3dh3q9kjv foreign key (qid) references q1002 (id)
Hibernate: alter table q1002 add constraint FK1ap2g6pq36pyrpjaw5o31yxdf foreign key (id) references q1002 (id)
Hibernate: select max(id) from q1002
Hibernate: select max(id) from a1002
Hibernate: insert into q1002 (qname, id) values (?, ?)
Hibernate: insert into a1002 (answername, postedBy, qid, id) values (?, ?, ?, ?)
Hibernate: insert into a1002 (answername, postedBy, qid, id) values (?, ?, ?, ?)
success

執行 FetchData.java得到以下結果 -

log4j:WARN No appenders could be found for logger (org.jboss.logging).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Sun Mar 26 23:42:52 CST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
Hibernate: select question0_.id as id1_1_, question0_.qname as qname2_1_ from q1002 question0_
Question Name: What is Java?
Hibernate: select answers0_.qid as qid4_0_0_, answers0_.id as id1_0_0_, answers0_.id as id1_0_1_, answers0_.answername as answerna2_0_1_, answers0_.postedBy as postedBy3_0_1_, answers0_.qid as qid4_0_1_ from a1002 answers0_ where answers0_.qid=?
java is a platform
java is a programming language
success