實體BEAN的七種關系之---------多對多雙向
Many-to-Many Bidirectional Relationship
一般來說,多對多的雙向發生在雙方都持有對方的很多引用,A可能持有很多個B,B也可能持有很多個A,并且A和B之間還要求能夠互相查詢.在現實中,我們可以用如下的例子來說明這種關系:
人和航班,一個人可以訂很多次航班,可以是訂了今天的,也可以訂明天的,因為他工作繁忙,同樣的,一個航班不可能只為一個人而開,也可以接受很多個人的預訂.并且這種查詢是雙向的,一個人他可以查詢他訂了多少個航班,一個航班也可以查詢它被多少人訂了,這樣才好根據訂的情況進行安排.
先看看代碼吧.
還是老樣子,Person類的代碼
/*
* Person.java
*
* Created on 2007-9-15, 0:11:58
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package lbf.entitybean.test1;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
/**
*
* @author Admin
*/
@Entity
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private String sex;
private int age;
private Address address;
private List<Phone> phones;
private IDCard idCard;
private Country country;
private List<Car> cars;
private List<Flight> flights;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "PersonANDFlight", joinColumns = {@JoinColumn(name = "personID")}, inverseJoinColumns = {@JoinColumn(name = "flightID")})
public List<Flight> getFlights() {
return flights;
}
public void setFlights(List<Flight> flights) {
this.flights = flights;
}
@OneToMany(cascade = CascadeType.ALL, mappedBy = "person")
public List<Car> getCars() {
return cars;
}
public void setCars(List<Car> cars) {
this.cars = cars;
}
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "countryID")
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
@OneToOne(cascade = CascadeType.ALL)
public IDCard getIdCard() {
return idCard;
}
public void setIdCard(IDCard idCard) {
this.idCard = idCard;
}
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "personID")
public List<Phone> getPhones() {
return phones;
}
public void setPhones(List<Phone> phones) {
this.phones = phones;
}
@OneToOne(cascade = {CascadeType.ALL})
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void setId(Long id) {
this.id = id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
}
代表航班的Flight類的代碼:
/*
* Flight.java
*
* Created on 2007-9-24, 14:35:45
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package lbf.entitybean.test1;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Temporal;
/**
*
* @author hadeslee
*/
@Entity
public class Flight implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@Temporal(javax.persistence.TemporalType.TIME)
public Date getArriveTime() {
return arriveTime;
}
public void setArriveTime(Date arriveTime) {
this.arriveTime = arriveTime;
}
public String getFlightNumber() {
return flightNumber;
}
public void setFlightNumber(String flightNumber) {
this.flightNumber = flightNumber;
}
public String getFromCity() {
return fromCity;
}
public void setFromCity(String fromCity) {
this.fromCity = fromCity;
}
@Temporal(javax.persistence.TemporalType.TIME)
public Date getLeaveTime() {
return leaveTime;
}
public void setLeaveTime(Date leaveTime) {
this.leaveTime = leaveTime;
}
@ManyToMany(mappedBy="flights")
public List<Person> getPersons() {
return persons;
}
public void setPersons(List<Person> persons) {
this.persons = persons;
}
public String getToCity() {
return toCity;
}
public void setToCity(String toCity) {
this.toCity = toCity;
}
private String flightNumber;
private String fromCity,toCity;
private Date leaveTime,arriveTime;
private List<Person> persons;
public void setId(Long id) {
this.id = id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
}
我們再來看一看ManyToMany的聲明
public @interface ManyToMany
{
Class targetEntity( ) default void.class;
CascadeType[] cascade( ) default {};
FetchType fetch( ) default LAZY;
String mappedBy( ) default "";
}
從代碼可以看出,注釋都差不多,只不過多對多的時候,僅僅從兩張用外鍵相連是不夠的,必須生成一張用于連接的中間表.也就如下代碼所聲明的地方:
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "PersonANDFlight", joinColumns = {@JoinColumn(name = "personID")}, inverseJoinColumns = {@JoinColumn(name = "flightID")})
public List<Flight> getFlights() {
return flights;
}
我們聲明了一張用來連接的表,并且聲明了主控端的列名和反轉端的列名,其實這個聲明不是必要的,當我們不用@JoinTable來聲明的時候,JBOSS也會為我們自動生成一個連接用的表,表名默認是主控端的表名加上下劃線"_"再加上反轉端的表名.
從上面的注釋我們可以看出,此關系的主控端在Person這一方,因為我們可以在Flight那一方看到如下注釋:
@ManyToMany(mappedBy="flights")
public List<Person> getPersons() {
return persons;
}
正是因為雙向關系的存在,也由于Person是主控端, 所以Person要取消某次預定只要remove相應的Flight就可以了,而Flight由于是反轉端,所以雖然它也可以得到它的所有預定的人,但是它卻無法改變這種關系,即使它remove掉了某個Person,但是這種關系并不會在數據庫里面表現出來,因為畢竟航班是不能隨便取消一個人的登機資格的.
其實按我的理解來說,多對多的雙向有點類似于一對多的單向,只不過雙方都是一對多,我們這個例子完全可以用一對多來實現,但是一對多實現的話,就會有很多重復的數據存在,因為每個關系都可能會有重復的元素,比如我們這個例子,如果一對多的話,每個航班都會對應幾百人,哪怕這幾百人下次還坐你的航班,你還要重新定義一下.因為上次的幾百人的外鍵已經指向你了.還要再指向另一個你,必須要重新生成幾百個元素,所以在這種情況下,多對多就可以很好的重用數據庫里面的表了,在Person和Flight表中,都不會有重復的元素存在了.并且關系也明朗了許多.
盡管千里冰封
依然擁有晴空
你我共同品味JAVA的濃香.
posted on 2007-09-25 09:00
千里冰封 閱讀(1100)
評論(3) 編輯 收藏 所屬分類:
JAVAEE