go4it

just do it

三种双向关系

1.person和IDCard的一对一双向关系

  person中

@OneToOne(cascade={CascadeType.ALL},optional=true)
    public IDCard getIdCard() {
        return idCard;
    }

 

IDCard中:

@OneToOne(cascade=CascadeType.ALL,mappedBy="idCard",optional=false)
    public Person getPerson() {
        return person;
    }

其中person为主控方,关系的维护者,它的表里有指向IDCard的外键。

 

----------------------------------------------------------------------

2.person和car的一对多双向关系:

person中:

@OneToMany(cascade=CascadeType.ALL,mappedBy="person")
    public List<Car> getCars() {
        return cars;
    }

 

car中:

@ManyToOne(cascade=CascadeType.ALL,optional=false)
    @JoinColumn(name="personID")
    public Person getPerson() {
        return person;
    }

一对多或者说多一对的双向关系中,主控端必须是多的那一方,也就是Car,在它里面起一个外键指向Person类的主键,

然后我们在对它们进行处理的时候,必须两端都要设置一下,才能保证数据的更新是如我们所愿的,比如
Person p=new Person();
Car car=new Car();
....
p.setCar(car);
car.setPerson(p);

entityManager.persist(p);
这个时候会把car和p都写入数据库
,当我们要把car的主人换成p1时,需要做如下动作
p.getCars().remove(car);
car.setPerson(p1);
p1.setCar(car);
这样就可以了,其实只要我们保持一个良好的习惯,那就是更新关系的时候,双方都更新一下,这样就不容易出错了.

----------------------------------------------------------------------

3.person和flight的多对多双向关联:

在person中

@ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "PersonANDFlight",
         joinColumns = {@JoinColumn(name = "personID")}, 
        inverseJoinColumns = {@JoinColumn(name = "flightID")})
    public List<Flight> getFlights() {
        return flights;
    }

 

在fight中:

@ManyToMany(mappedBy="flights")
    public List<Person> getPersons() {
        return persons;
    }

从代码可以看出,注释都差不多,只不过多对多的时候,仅仅从两张用外键相连是不够的,必须生成一张用于连接的中间表.也就如下代码所声明的地方:

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

posted on 2009-01-22 17:59  cxccbv  阅读(1190)  评论(0编辑  收藏  举报

导航