EJB学习日记(13)

来源:互联网 发布:姿态矩阵 姿态角 编辑:程序博客网 时间:2024/06/06 23:16
2007年10月10日 07:01:00

实体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表中,都不会有重复的元素存在了.并且关系也明朗了许多.

来自:千里冰封

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1817688


原创粉丝点击