Hibernate多對多兩種狀況

Hibernate在作多對多映射的時候,除了原先的兩張表外,會多出一箇中間表作關聯,根據中間表的會有兩種不一樣的配置狀況:web

1.中間表不須要加入額外數據。app

2.中間表有其餘字段,需記錄額外數據。測試

下面,咱們就以address、person這兩張表根據這兩種狀況作下相應的配置:this

狀況1:spa

咱們須要建三張表,一張address表,一張person表,一張中間表(其實中間表能夠不用建,配置好後運行會自動生成),以下:.net

delimiter $$CREATE TABLE `address` (
  `address_id` int(11) NOT NULL,
  `address_name` varchar(50) default NULL,  PRIMARY KEY  (`address_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

delimiter $$CREATE TABLE `person` (
  `person_id` int(11) NOT NULL,
  `person_name` varchar(20) default NULL,  PRIMARY KEY  (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

delimiter $$CREATE TABLE `person_address` (
  `person_id` int(11) NOT NULL,
  `address_id` int(11) NOT NULL,  PRIMARY KEY  (`address_id`,`person_id`),  KEY `FK23F8B90AAAA29DA8` (`person_id`),  KEY `FK23F8B90AB52F16EC` (`address_id`),  CONSTRAINT `FK23F8B90AB52F16EC` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`),  CONSTRAINT `FK23F8B90AAAA29DA8` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$


表建好後,咱們須要寫相應的實體類:hibernate


public class Address {    
    private int addressId;    private String addressName;    private Set<Person> person;    
    public int getAddressId() {        return addressId;
    }    public void setAddressId(int addressId) {        this.addressId = addressId;
    }    public String getAddressName() {        return addressName;
    }    public void setAddressName(String addressName) {        this.addressName = addressName;
    }    public Set<Person> getPerson() {        return person;
    }    public void setPerson(Set<Person> person) {        this.person = person;
    }
    
}public class Person {    
    private int personId;    private String personName;    private Set<Address> address;    
    public int getPersonId() {        return personId;
    }    public void setPersonId(int personId) {        this.personId = personId;
    }    
    public String getPersonName() {        return personName;
    }    public void setPersonName(String personName) {        this.personName = personName;
    }    public Set<Address> getAddress() {        return address;
    }    public void setAddress(Set<Address> address) {        this.address = address;
    }
        
}


在這裏,咱們只須要配置兩個實體類與相應配置文件便可,中間表無須建實體類與配置文件,hibernate會幫你自動關連。code


<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.test.web.model">

    <class name="Address" table="address">
        <id name="addressId" type="int" >
            <column name="address_id" length="11"></column> 
        </id>
        <property name="addressName" type="string" >
            <column name="address_name" length="50"></column>
        </property>
        <set name="person" cascade="all" table="person_address">
            <key column="address_id"></key>
            <many-to-many class="Person" column="person_id"/>
        </set>
    </class></hibernate-mapping><?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.test.web.model">

    <class name="Person" table="person">
        <id name="personId" type="int" >
            <column name="person_id" length="11"></column> 
        </id>
        <property name="personName" type="string" >
            <column name="person_name" length="20"></column>
        </property>
        <set name="address" cascade="all" table="person_address">
            <key column="person_id"></key>
            <many-to-many class="Address" column="address_id"/>
        </set>
    </class></hibernate-mapping>


測試類:xml


public void insert() {
        
        Person p = new Person();
        p.setPersonId(1);
        p.setPersonName("newUser");
        Address ad = new Address();
        ad.setAddressId(2);
        ad.setAddressName("here");
        Set<Address> setAd = new HashSet<Address>();
        setAd.add(ad);
         p.setAddress(setAd);
        sf.getCurrentSession().persist(p);
}


以上,即是通常的多對多關係。接口

狀況2:

  當須要向中間表寫數據時,單純的多對多已經知足不了了,因此在這裏,咱們能夠將其設成兩個一對多的關係,即person表與 person_address是一對多關係,address與person_address表也是一對多關係,這樣,但能夠完成相應的多對多功能了。在情 況2中,咱們不僅僅須要對person表與address表寫相應的實體類與配置文件,還須要對person_address表寫實體類與配置文件。

     在第二種狀況中,咱們又能夠分紅兩種小的狀況:

  1)中間表新增主鍵,另有兩個字段作爲外鍵對應另外兩張表。

      2)中間表採用複合主鍵,同時作爲外鍵分別對應另外兩張表。

下面咱們分別對兩種狀況作相應配置。

狀況1)中間表新增主鍵,另有兩個字段作爲外鍵對應另外兩張表。數據表結構爲:


delimiter $$CREATE TABLE `address` (
  `address_id` int(11) NOT NULL,
  `address_name` varchar(50) default NULL,  PRIMARY KEY  (`address_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

delimiter $$CREATE TABLE `person` (
  `person_id` int(11) NOT NULL,
  `person_name` varchar(20) default NULL,  PRIMARY KEY  (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$


delimiter $$CREATE TABLE `person_address` (
  `pa_id` int(11) NOT NULL,
  `person_id` int(11) default NULL,
  `address_id` int(11) default NULL,
  `pa_describe` varchar(50) default NULL,  PRIMARY KEY  (`pa_id`),  KEY `FK23F8B90AAAA29DA8` (`person_id`),  KEY `FK23F8B90AB52F16EC` (`address_id`),  CONSTRAINT `FK23F8B90AB52F16EC` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`),  CONSTRAINT `FK23F8B90AAAA29DA8` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$


對應的類爲:


public class Address {    
    private int addressId;    private String addressName;    private Set<PersonAddress> pa;    
    public int getAddressId() {        return addressId;
    }    public void setAddressId(int addressId) {        this.addressId = addressId;
    }    public String getAddressName() {        return addressName;
    }    public void setAddressName(String addressName) {        this.addressName = addressName;
    }    public Set<PersonAddress> getPa() {        return pa;
    }    public void setPa(Set<PersonAddress> pa) {        this.pa = pa;
    }
    
}public class Person {    
    private int personId;    private String personName;    private Set<PersonAddress> personAddress;    
    public int getPersonId() {        return personId;
    }    public void setPersonId(int personId) {        this.personId = personId;
    }    
    public String getPersonName() {        return personName;
    }    public void setPersonName(String personName) {        this.personName = personName;
    }    public Set<PersonAddress> getPersonAddress() {        return personAddress;
    }    public void setPersonAddress(Set<PersonAddress> personAddress) {        this.personAddress = personAddress;
    }    
}public class PersonAddress{    
    private int paid;    private String paDescribe;    private Person person;    private Address address;    
    
    public int getPaid() {        return paid;
    }    public void setPaid(int paid) {        this.paid = paid;
    }    public String getPaDescribe() {        return paDescribe;
    }    public void setPaDescribe(String paDescribe) {        this.paDescribe = paDescribe;
    }    public Person getPerson() {        return person;
    }    public void setPerson(Person person) {        this.person = person;
    }    public Address getAddress() {        return address;
    }    public void setAddress(Address address) {        this.address = address;
    }
    
}


配置文件:


<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.test.web.model">

    <class name="Address" table="address">
        <id name="addressId" type="int" >
            <column name="address_id" length="11"></column> 
        </id>
        <property name="addressName" type="string" >
            <column name="address_name" length="50"></column>
        </property>
        <set name="pa" cascade="all">
            <key column="address_id"></key>
            <one-to-many class="PersonAddress"/>
        </set>
    </class></hibernate-mapping><?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.test.web.model">

    <class name="Person" table="person">
        <id name="personId" type="int" >
            <column name="person_id" length="11"></column> 
        </id>
        <property name="personName" type="string" >
            <column name="person_name" length="20"></column>
        </property>
        <set name="personAddress" cascade="all">
            <key column="person_id"></key>
            <one-to-many class="PersonAddress"/>
        </set>
    </class></hibernate-mapping><?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.test.web.model">

    <class name="PersonAddress" table="person_address">
        <id name="paid" type="int">
            <column name="pa_id" length="11"></column>
        </id>
        <property name="paDescribe" type="string" >
            <column name="pa_describe" length="50"></column>
        </property>
        <many-to-one name="person" class="Person" cascade="all">
            <column name="person_id" length="11" ></column>
        </many-to-one>
        <many-to-one name="address" class="Address" cascade="all">
            <column name="address_id" length="11" ></column>
        </many-to-one>
    </class></hibernate-mapping>


以上,便完成了相應的配置,進行數據插入時,只需應對相應的保存便可,如:


public void insert() {
        
        Person p = new Person();
        p.setPersonId(1);
        p.setPersonName("newUser");
        Address ad = new Address();
        ad.setAddressId(2);
        ad.setAddressName("here");
        PersonAddress pa = new PersonAddress();
        pa.setPaid(1);
        pa.setPerson(p);
        pa.setAddress(ad);
        pa.setPaDescribe("this is a test");
        sf.getCurrentSession().persist(pa);
}


 狀況2)中間表採用複合主鍵,同時作爲外鍵分別對應另外兩張表。因爲採用複合主鍵,在hibernate模型中,須要有另外一個類來對應,並實現Serializable接口:


public class PersonAddressPK implements Serializable{    
    /**
     * 
     */
    private static final long serialVersionUID = 1L;    
    private int person;    private int address;    public int getPerson() {        return person;
    }    public void setPerson(int person) {        this.person = person;
    }    public int getAddress() {        return address;
    }    public void setAddress(int address) {        this.address = address;
    }
    

}


Person表與address表不變,主要是在person_address表上作修改,以下:

delimiter $$
 
CREATE     TABLE     `person_address` (
       `person_id`     int     (11)     NOT     NULL     ,
       `address_id`     int     (11)     NOT     NULL     ,
       `pa_describe`     varchar     (50)     default     NULL     ,
       PRIMARY     KEY      (`person_id`,`address_id`),
       KEY     `FK23F8B90AAAA29DA8` (`person_id`),
       KEY     `FK23F8B90AB52F16EC` (`address_id`),
       CONSTRAINT     `FK23F8B90AB52F16EC`     FOREIGN     KEY     (`address_id`)     REFERENCES     `address` (`address_id`),
       CONSTRAINT     `FK23F8B90AAAA29DA8`     FOREIGN     KEY     (`person_id`)     REFERENCES     `person` (`person_id`)
) ENGINE=InnoDB     DEFAULT     CHARSET=utf8$$

相應的類:


public class PersonAddress{    
    
    private String paDescribe;    private PersonAddressPK paPK;    private Person person;    private Address address;    
    public String getPaDescribe() {        return paDescribe;
    }    public void setPaDescribe(String paDescribe) {        this.paDescribe = paDescribe;
    }    public PersonAddressPK getPaPK() {        return paPK;
    }    public void setPaPK(PersonAddressPK paPK) {        this.paPK = paPK;
    }    public Person getPerson() {        return person;
    }    public void setPerson(Person person) {        this.person = person;
    }    public Address getAddress() {        return address;
    }    public void setAddress(Address address) {        this.address = address;
    }
    
    
}


配置文件:


<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.test.web.model">

    <class name="PersonAddress" table="person_address">
        <composite-id class="PersonAddressPK" name="paPK">
            <key-property name="person">
                <column name="person_id" length="11"></column>
            </key-property>
            <key-property name="address">
                <column name="address_id" length="11"></column>
            </key-property>
        </composite-id>
        <property name="paDescribe" type="string" >
            <column name="pa_describe" length="50"></column>
        </property>
        <many-to-one name="person" class="Person" column="person_id" insert="false" update="false"/>  
        <many-to-one name="address" class="Address" column="address_id" insert="false" update="false"/>
    </class></hibernate-mapping>


插入的時候,需先保存person與address表,再保存person_address表:


public void insert() {
        
        Person p = new Person();
        p.setPersonId(1);
        p.setPersonName("newUser");
        Address ad = new Address();
        ad.setAddressId(2);
        ad.setAddressName("here");
        sf.getCurrentSession().persist(p);
        sf.getCurrentSession().persist(ad);
        PersonAddress pa = new PersonAddress();
        PersonAddressPK paPK = new PersonAddressPK();
        paPK.setPerson(p.getPersonId());
        paPK.setAddress(ad.getAddressId());
        pa.setPaPK(paPK);
        pa.setPaDescribe("this is a test");
        sf.getCurrentSession().persist(pa);
}


 以上,即是hibernate多對多時可採用的幾種方法了。

相關文章
相關標籤/搜索