4.2.3.2. Many-to-Many Association with Link Entity
The many-to-many association is always implemented using a joining table, but creating an entity to reflect this table is optional. The joining entity can be created in case you want to store some additional fields in the joining table.
Let’s demonstrate this approach using the Airport and the DutyFree entities as an example. Many different duty-free shops can be located in one airport, and one duty-free shop can be represented in many different airports. Suppose that we want to store the link airport-shop and the currency used in this shop and this airport:
-
Airport.java - the
Airportentity contains a one-to-many composition ofAirportDutyFreeinstances.In the Studio entity designer, set for the
dutyFreeShopsattribute: Attribute type -COMPOSITION, Cardinality -ONE_TO_MANY.@Composition @OnDelete(DeletePolicy.CASCADE) @OneToMany(mappedBy = "airport") protected List<AirportDutyFree> dutyFreeShops; -
DutyFree.java - the
DutyFreeentity contains a one-to-many composition ofAirportDutyFreeinstances, too.In the Studio entity designer, set for the
airportsattribute: Attribute type -COMPOSITION, Cardinality -ONE_TO_MANY.@Composition @OnDelete(DeletePolicy.CASCADE) @OneToMany(mappedBy = "dutyFree") protected List<AirportDutyFree> airports; -
AirportDutyFree.java - thus, the
AirportDutyFreeentity contains two many-to-one references:airportanddutyFree.@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "AIRPORT_ID") protected Airport airport; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "DUTY_FREE_ID") protected DutyFree dutyFree; @Column(name = "CURRENCY") protected Integer currency; -
views.xml - the
airport-duty-freeview of the airport editing screen contains the composition ofdutyFreeShops(referencing theAirportDutyFreejoining entity) withdutyFreeandcurrencyattributes.The
dutyFree-airportview follows the same logic: it includes the composition ofairports(referencing theAirportDutyFreejoining entity) withairportandcurrencyattributes. -
duty-free-edit.xml - the XML descriptor of the duty-free shop editor defines a datasource for the
DutyFreeinstance and a nested one for its airports. It also contains a table displaying airports and the custom action to pick an airport directly, bypassing theAirportDutyFreeeditor.
As a result, editing of a DutyFree instance works as follows:
The DutyFree edit screen shows a list of airports and the currency drop-down.
A user can click Add airport, the Airport lookup will be opened, and the user can either select an airport to add or open its editor. When the user selects an airport, the new AirportDutyFree instance is created with the default currency. This instance it is not saved to the database, but added to the airportsDs datasource of the DutyFree editor.
When OK is clicked in the Airport editor, the updated instance of the airport is saved both to the database and to the airportsDs datasource of the DutyFree editor, as the Airport entity is fully independent.
The user can create new airports and delete existing ones, and all changes will be saved to the database in separate transactions and to the airportsDs datasource as well.
When a user clicks OK in the duty-free edit screen, the updated DutyFree instance together with all the updated AirportDutyFree instances is submitted to the DataManager.commit() method on the middleware and saved to the database within a single transaction.