Skip to content

Lesson 5 Practice — Booking Associations ​

In Lesson 4 practice, you solved the booking problem with explicit joins. The guided Lesson 5 material now provides the association concepts you will apply here.

Now solve the same kind of problem with reusable CDS relationships.

Your architecture will be:

text
/DMO/BOOKING
      ↓
ZI_BOOKING_ASSOC_###
      ├── _Customer ───► /DMO/I_CUSTOMER
      ├── _Carrier ────► /DMO/I_CARRIER
      └── _Connection ─► /DMO/I_CONNECTION
              ↓
       Booking Reader
              ↓
           Runner

The complete solution is intentionally not included here.


Objects to create ​

text
ZI_BOOKING_ASSOC_###
ZCL_BOOKING_ASSOC_READER_###
ZCL_CDS_L05_PRACTICE_###

Optional challenge:

text
ZI_CARRIER_CONNECTIONS_###

Replace ### with your student/group suffix.


Part 1 — Inspect the target CDS entities ​

Open each target using:

text
Ctrl + Shift + A

Inspect:

text
/DMO/I_CUSTOMER
/DMO/I_CARRIER
/DMO/I_CONNECTION

Record the keys.

/DMO/I_CUSTOMER ​

text
Key:

/DMO/I_CARRIER ​

text
Key:

/DMO/I_CONNECTION ​

text
Key field 1:
Key field 2:

Do not continue until you know the complete key of /DMO/I_CONNECTION.


Part 2 — Inspect /DMO/BOOKING ​

Open:

text
/DMO/BOOKING

Identify:

text
travel_id
booking_id
booking_date
customer_id
carrier_id
connection_id
flight_date
flight_price
currency_code

Confirm the booking key:

text
travel_id + booking_id

Part 3 — Plan the relationships ​

Complete:

text
Booking.customer_id
    → ______________________________

Booking.carrier_id
    → ______________________________

Booking.carrier_id + Booking.connection_id
    → ______________________________

For each relationship, decide:

text
to-one or to-many?

Write a one-sentence reason for each answer.


Part 4 — Create ZI_BOOKING_ASSOC_### ​

Create a Data Definition.

Use:

text
Name:        ZI_BOOKING_ASSOC_###
Description: Lesson 5 - Booking Associations

Choose a CDS View Entity template.

Primary source:

text
/DMO/BOOKING

Alias:

text
Booking

Part 5 — Build the base model first ​

Before adding associations, expose:

text
TravelId
BookingId
BookingDate
CustomerId
CarrierId
ConnectionId
FlightDate
FlightPrice
CurrencyCode

Mark only the booking identifier fields as CDS keys.

Run:

text
Ctrl + F2

Activate:

text
Ctrl + F3

Preview:

text
F8

Part 6 — Define _Customer ​

Create an association to:

text
/DMO/I_CUSTOMER

Use the name:

text
_Customer

Choose the cardinality based on:

text
one booking → how many customer targets?

Use:

text
$projection.CustomerId

in the ON condition.

Hint

The target key is named:

text
CustomerID

Part 7 — Add Customer path fields ​

Through _Customer, expose:

text
CustomerFirstName
CustomerLastName

The target fields are:

text
FirstName
LastName

Use CDS path expressions.


Part 8 — Expose _Customer ​

Add:

abap
_Customer

itself to the element list.

Activate.

Open Data Preview.

Use:

text
Follow Association
  → _Customer

Confirm that ADT navigates to the related customer data.


Part 9 — Define _Carrier ​

Create an association to:

text
/DMO/I_CARRIER

Use:

text
_Carrier

Use the current projection's:

text
CarrierId

in the relationship condition.

Expose the target's:

text
Name

as:

text
CarrierName

Then expose:

text
_Carrier

itself.


Part 10 — Follow _Carrier ​

Activate.

Open Data Preview.

Choose:

text
Follow Association
  → _Carrier

Verify target fields such as:

text
AirlineID
Name
CurrencyCode

against the booking's CarrierId.


Part 11 — Define _Connection ​

This is the key reasoning task.

Target:

text
/DMO/I_CONNECTION

Association name:

text
_Connection

Before writing the ON condition, answer:

What is the complete target key?

The booking provides:

text
CarrierId
ConnectionId

Your association must use the complete relationship.

WARNING

Do not associate only on ConnectionId.

/DMO/I_CONNECTION has a composite key.

Hint

Your condition needs two comparisons joined with:

abap
and

Part 12 — Add Connection path fields ​

Through _Connection, expose:

text
DepartureAirportId
DestinationAirportId
DepartureTime
ArrivalTime

The target provides:

text
DepartureAirport
DestinationAirport
DepartureTime
ArrivalTime

Part 13 — Expose _Connection ​

Add:

abap
_Connection

to the element list.

Activate.

Open Data Preview and use:

text
Follow Association
  → _Connection

Check that the target:

text
AirlineID
ConnectionID

matches:

text
CarrierId
ConnectionId

from the booking.


Part 14 — Final scalar model requirements ​

Your CDS entity should expose:

text
TravelId
BookingId
BookingDate

CustomerId
CustomerFirstName
CustomerLastName

CarrierId
CarrierName

ConnectionId
DepartureAirportId
DestinationAirportId
DepartureTime
ArrivalTime

FlightDate
FlightPrice
CurrencyCode

It should also expose:

text
_Customer
_Carrier
_Connection

Part 15 — Compare the Lesson 4 and Lesson 5 designs ​

Write:

text
Lesson 4:
Booking __________ Customer

Lesson 5:
Booking __________ Customer

Use:

text
JOIN
ASSOCIATION

Then answer:

What capability does the exposed association provide that a copied CustomerName scalar field alone does not?


Part 16 — SQL Console ​

Query:

text
ZI_BOOKING_ASSOC_###

Return at least:

text
TravelId
BookingId
CustomerFirstName
CustomerLastName
CarrierName
DepartureAirportId
DestinationAirportId
FlightDate

Order by:

text
TravelId
BookingId

The SQL query should not contain joins to Customer, Carrier, or Connection.


Part 17 — Filter by Carrier ​

Choose a CarrierId present in your booking data.

Filter in SQL Console.

Confirm that:

text
CarrierName

is available even though it came through an association path.


Part 18 — Create the Reader ​

Create:

text
ZCL_BOOKING_ASSOC_READER_###

Do not implement:

text
IF_OO_ADT_CLASSRUN

Define:

text
TT_BOOKINGS

as a standard table of:

text
ZI_BOOKING_ASSOC_###

with:

text
WITH EMPTY KEY

Part 19 — Implement GET_ALL ​

Create:

text
GET_ALL

Requirements:

  • return TT_BOOKINGS;
  • select from ZI_BOOKING_ASSOC_###;
  • use FIELDS *;
  • order by TravelId, BookingId;
  • contain no explicit joins;
  • contain no association definitions.

Part 20 — Implement GET_BY_CARRIER ​

Create:

text
GET_BY_CARRIER

Import:

text
carrier_id

Requirements:

  • select from ZI_BOOKING_ASSOC_###;
  • filter on CarrierId;
  • use an ABAP SQL host variable;
  • return TT_BOOKINGS;
  • order by the booking key.

Part 21 — Create the Runner ​

Create:

text
ZCL_CDS_L05_PRACTICE_###

Implement:

text
IF_OO_ADT_CLASSRUN

In main:

  1. instantiate the Reader;
  2. call GET_ALL;
  3. loop through the result;
  4. display a useful line containing:
text
TravelId/BookingId
FirstName LastName
CarrierName
DepartureAirportId → DestinationAirportId

Design the exact format yourself.


Part 22 — Test GET_BY_CARRIER ​

Use a carrier ID present in your tenant.

Call:

text
GET_BY_CARRIER

Display the result.

Confirm the architecture:

text
Runner
  ↓
Reader
  ↓
ZI_BOOKING_ASSOC_###
  ↓
associations

The Reader and Runner should not recreate the relationships.


Part 23 — Cardinality table ​

Complete:

AssociationCardinalityWhy?
_Customer
_Carrier
_Connection

Your reason must answer:

How many target records are expected for one booking?


Part 24 — Explain a path expression ​

For:

abap
_Carrier.Name

answer:

What is _Carrier? ​

What is Name? ​

What scalar element did you create from this path? ​

What database join behavior is generated by default for a CDS path target field? ​


Part 25 — Scalar field vs exposed association ​

Explain the difference between:

abap
_Carrier.Name as CarrierName

and:

abap
_Carrier

Use:

text
scalar value
relationship
navigation

in your explanation.


Part 26 — Direction ​

Your model contains:

text
Booking → Customer

Does that automatically add:

text
Customer → Booking

Explain why or why not.


Part 27 — Optional challenge: Carrier → Connections ​

Create:

text
ZI_CARRIER_CONNECTIONS_###

Primary source:

text
/DMO/I_CARRIER

Alias:

text
Carrier

Expose:

text
CarrierId
CarrierName

Create an association:

text
_Connections

to:

text
/DMO/I_CONNECTION

Decide cardinality based on:

text
one carrier → how many connections?

Expose the association itself.

Do not flatten every connection field into the carrier row.


Part 28 — Follow the to-many association ​

Activate:

text
ZI_CARRIER_CONNECTIONS_###

Open Data Preview.

Use:

text
Follow Association
  → _Connections

Inspect the related connection records.

Answer:

Why is _Connections not [1..1]? ​

Why can one source carrier lead to several target rows? ​


Part 29 — Connect to Lesson 4 row multiplication ​

Answer:

If you flatten a target field through a to-many association, why can one source row become several result rows?

Use the Lesson 4 concept:

text
row multiplication

Part 30 — Reasoning questions ​

Answer in your own words.

1. What does a CDS association represent? ​

2. How is an association different from an explicit join? ​

3. Why are associations directional? ​

4. What does cardinality describe? ​

5. Why is _Connection a to-one relationship from Booking? ​

6. Why must _Connection use both CarrierId and ConnectionId? ​

7. What does $projection.CustomerId mean? ​

8. What does _Customer.LastName mean? ​

9. What happens when a path target field is used in a CDS element list? ​

10. What does exposing _Customer add to the public CDS model? ​

11. What ADT feature lets you inspect an exposed association? ​

12. Why can Carrier → Connections be [0..*] while Booking → Carrier is [1..1]? ​

13. Why is cardinality more than documentation? ​

14. How do associations prepare a CDS model for later RAP/service navigation? ​


Submission checklist ​


Useful ADT shortcuts ​

ActionShortcut
Open ABAP Development ObjectCtrl + Shift + A
Code completionCtrl + Space
NavigateF3 / Ctrl + click where supported
Syntax checkCtrl + F2
Activate current objectCtrl + F3
Activate inactive objectsCtrl + Shift + F3
CDS Data PreviewF8
Run console classF9
Format sourceShift + F1