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多對多時可採用的幾種方法了。