7.1.3.2. 使用连接实体进行多对多关联

在线示例

多对多关联的实现始终要用到一个连接表(joining table),但是,为这个中间表创建对应的实体却不是必须的。如果需要在连接表中存储一些其它字段,这时就有必要创建连接实体了。

AirportDutyFree 实体为例来演示这种方法。许多不同的免税店可以在一个机场内,并且一个品牌的免税店可以出现在许多不同机场中。假设我们想要存储机场和免税店的对应关系以及此关系中可使用的货币信息:

association recipe 2

  • Airport.java - Airport 实体包含 AirportDutyFree 实例的一对多组合。

在 Studio 实体设计器中,设置 dutyFreeShops 属性: Attribute type - COMPOSITIONCardinality - ONE_TO_MANY

  1. @Composition
  2. @OnDelete(DeletePolicy.CASCADE)
  3. @OneToMany(mappedBy = "airport")
  4. protected List<AirportDutyFree> dutyFreeShops;
  • DutyFree.java - DutyFree 实体也包含 AirportDutyFree 实例的一对多组合。

在 Studio 实体设计器中,设置 airports 属性:属性类型 - COMPOSITION,Cardinality - ONE_TO_MANY.

  1. @Composition
  2. @OnDelete(DeletePolicy.CASCADE)
  3. @OneToMany(mappedBy = "dutyFree")
  4. protected List<AirportDutyFree> airports;
  • AirportDutyFree.java - 因此,AirportDutyFree 实体包含两个多对一引用: airportdutyFree
  1. @ManyToOne(fetch = FetchType.LAZY)
  2. @JoinColumn(name = "AIRPORT_ID")
  3. protected Airport airport;
  4. @ManyToOne(fetch = FetchType.LAZY)
  5. @JoinColumn(name = "DUTY_FREE_ID")
  6. protected DutyFree dutyFree;
  7. @Column(name = "CURRENCY")
  8. protected Integer currency;
  • views.xml - 机场编辑界面的 airport-dutyfree 视图组合了带有 dutyFreecurrency 属性的 dutyFreeShops (引用 AirportDutyFree 关联实体)实体。

dutyFree-airport 视图遵循相同的逻辑:组合了带有 airportcurrency 属性的 airports (引用 AirportDutyFree 关联实体)实体。(参考 views.xml 内容进行理解)

  • duty-free-edit.xml - 免税店编辑界面的 XML 描述定义了 DutyFree 实例的数据源和其机场实例的嵌套数据源。还包含一个显示机场的表格和直接选择机场的自定义操作,而不使用 AirportDutyFree 编辑界面。

因此,编辑 DutyFree 实例的工作方式如下:

DutyFree 编辑界面显示一个机场列表和货币下拉列表。

用户可以点击 Add airport,将打开 Airport 查找,且用户可以选择要添加的机场或打开其编辑界面。当用户选择机场时,新的 AirportDutyFree 实例使用默认货币 进行创建。这个实例不会保存到数据库中,而是添加到 DutyFree 编辑界面的 airportsDs 数据源中。

Airport 编辑界面 中点击确定时,更新后的机场实例既保存到数据库又保存到 DutyFree 编辑界面的 airportsDs 数据源,因为 Airport 实体是完全独立的。

用户可以创建新机场和移除现有机场,所有更改将在单独的事务中保存到数据库,同时也保存到 airportsDs 数据源。

当用户在免税店编辑界面中点击确定时,更新的 DutyFree 实例与所有更新的 AirportDutyFree 实例将一起被提交到中间层的 DataManager.commit() 方法并使用单个事务保存到数据库中。