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多对多时可采用的几种方法了。

相关文章
相关标签/搜索