El RAP clásico requiere múltiples capas: tabla de base de datos, Interface CDS View, Projection View, Behavior Definition y Service Definition. El RAP CDS Pattern (también llamado CDS-only Pattern) simplifica significativamente esta arquitectura - con Table Entities como elemento central.
El Problema: Demasiados Objetos
Para una aplicación CRUD simple, el stack RAP clásico requiere:
1. Tabla de base de datos (ZFLIGHT_BOOK)2. Interface CDS View (ZI_FlightBooking)3. Projection CDS View (ZC_FlightBooking)4. Behavior Definition (ZI_FlightBooking)5. Behavior Implementation (ZBP_I_FLIGHTBOOKING)6. Service Definition (ZUI_FLIGHTBOOKING)7. Service Binding (ZUI_FLIGHTBOOKING_O4)Para un objeto de datos simple, estos son siete objetos de desarrollo - mucho overhead para operaciones CRUD.
La Solución: Table Entities
Con Table Entities (introducidas con ABAP Cloud 2024), la tabla misma se convierte en la entidad:
1. Table Entity (ZI_FlightBooking) - Tabla + View en uno2. Behavior Definition (ZI_FlightBooking)3. Service Definition (ZUI_FLIGHTBOOKING)4. Service Binding (ZUI_FLIGHTBOOKING_O4)Solo cuatro objetos - y a menudo no se necesita Behavior Implementation.
Clásico vs. CDS Pattern
| Aspecto | Stack RAP Clásico | CDS Pattern |
|---|---|---|
| Objetos | 5-7 | 3-4 |
| Definición de tabla | DDL separado | En Table Entity |
| Interface View | CDS View propia | Table Entity mismo |
| Projection View | Requerida | Opcional |
| Flexibilidad | Máxima | CRUD estándar |
| Campos calculados | Sí | No |
| Aliases | Libre elección | Idéntico a columna |
| Recomendado para | BOs complejos | CRUD simple |
Ejemplo Completo: Reserva de Vuelo
Paso 1: Definir Table Entity
El Table Entity combina la definición de tabla y CDS View:
@EndUserText.label: 'Reserva de Vuelo'@AbapCatalog.enhancement.category: #NOT_EXTENSIBLE@AbapCatalog.tableCategory: #TRANSPARENT@AbapCatalog.deliveryClass: #A@AbapCatalog.dataMaintenance: #RESTRICTED
define table entity zi_flightbooking { key client : abap.clnt not null; key booking_id : abap.numc(10) not null;
// Datos de negocio flight_date : abap.dats; carrier_id : abap.char(3); connection_id : abap.numc(4); customer_id : abap.numc(10);
// Detalles de reserva @Semantics.amount.currencyCode: 'zi_flightbooking.currency_code' flight_price : abap.curr(15,2); currency_code : abap.cuky; booking_status : abap.char(1);
// Campos administrativos (¡importantes para RAP!) @Semantics.user.createdBy: true created_by : abap.uname; @Semantics.systemDateTime.createdAt: true created_at : abap.utclong; @Semantics.user.lastChangedBy: true last_changed_by : abap.uname; @Semantics.systemDateTime.lastChangedAt: true last_changed_at : abap.utclong; @Semantics.systemDateTime.localInstanceLastChangedAt: true local_last_changed : abap.utclong;}Importante: Las anotaciones Semantics para campos administrativos permiten el llenado automático por el framework RAP.
Paso 2: Behavior Definition
La Behavior Definition referencia directamente el Table Entity:
managed implementation in class zbp_i_flightbooking unique;strict ( 2 );
define behavior for zi_flightbooking alias FlightBookinglock masterauthorization master ( instance )etag master local_last_changed{ // CRUD estándar - El framework se encarga de todo create; update; delete;
// Campos de solo lectura field ( readonly ) booking_id; field ( readonly ) created_by, created_at, last_changed_by, last_changed_at; field ( readonly : update ) carrier_id, connection_id, flight_date;
// Numeración automática field ( numbering : managed ) booking_id;
// Actions simples action confirmBooking result [1] $self; action cancelBooking result [1] $self;
// Validación validation validateFlightDate on save { field flight_date; } validation validateCustomer on save { field customer_id; }
// Determination para estado determination setInitialStatus on modify { create; }
// Mapping - idéntico porque es Table Entity mapping for zi_flightbooking corresponding;}Paso 3: Service Definition
@EndUserText.label: 'Servicio de Reserva de Vuelo'define service ZUI_FLIGHTBOOKING { expose zi_flightbooking as FlightBooking;}Paso 4: Service Binding
Name: ZUI_FLIGHTBOOKING_O4Service: ZUI_FLIGHTBOOKINGBinding Type: OData V4 - UIDespués de activar y publicar, la aplicación Fiori Elements está lista.
Behavior Implementation (opcional)
Para Actions y validaciones, necesita una clase de implementación:
CLASS zbp_i_flightbooking DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF zi_flightbooking.ENDCLASS.
CLASS zbp_i_flightbooking IMPLEMENTATION.ENDCLASS.
CLASS lhc_flightbooking DEFINITION INHERITING FROM cl_abap_behavior_handler. PRIVATE SECTION. METHODS: confirmBooking FOR MODIFY IMPORTING keys FOR ACTION FlightBooking~confirmBooking RESULT result,
cancelBooking FOR MODIFY IMPORTING keys FOR ACTION FlightBooking~cancelBooking RESULT result,
validateFlightDate FOR VALIDATE ON SAVE IMPORTING keys FOR FlightBooking~validateFlightDate,
validateCustomer FOR VALIDATE ON SAVE IMPORTING keys FOR FlightBooking~validateCustomer,
setInitialStatus FOR DETERMINE ON MODIFY IMPORTING keys FOR FlightBooking~setInitialStatus.ENDCLASS.
CLASS lhc_flightbooking IMPLEMENTATION. METHOD confirmBooking. " Establecer estado a 'Confirmado' MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking UPDATE FIELDS ( booking_status ) WITH VALUE #( FOR key IN keys ( %tky = key-%tky booking_status = 'C' ) ).
" Devolver resultado READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(bookings).
result = VALUE #( FOR booking IN bookings ( %tky = booking-%tky %param = booking ) ). ENDMETHOD.
METHOD cancelBooking. MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking UPDATE FIELDS ( booking_status ) WITH VALUE #( FOR key IN keys ( %tky = key-%tky booking_status = 'X' ) ).
READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking ALL FIELDS WITH CORRESPONDING #( keys ) RESULT DATA(bookings).
result = VALUE #( FOR booking IN bookings ( %tky = booking-%tky %param = booking ) ). ENDMETHOD.
METHOD validateFlightDate. READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking FIELDS ( flight_date ) WITH CORRESPONDING #( keys ) RESULT DATA(bookings).
LOOP AT bookings INTO DATA(booking). IF booking-flight_date < cl_abap_context_info=>get_system_date( ). APPEND VALUE #( %tky = booking-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'La fecha del vuelo debe estar en el futuro' ) %element-flight_date = if_abap_behv=>mk-on ) TO reported-flightbooking.
APPEND VALUE #( %tky = booking-%tky ) TO failed-flightbooking. ENDIF. ENDLOOP. ENDMETHOD.
METHOD validateCustomer. " Implementar validación de cliente READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking FIELDS ( customer_id ) WITH CORRESPONDING #( keys ) RESULT DATA(bookings).
LOOP AT bookings INTO DATA(booking). IF booking-customer_id IS INITIAL. APPEND VALUE #( %tky = booking-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'Se debe especificar el cliente' ) %element-customer_id = if_abap_behv=>mk-on ) TO reported-flightbooking.
APPEND VALUE #( %tky = booking-%tky ) TO failed-flightbooking. ENDIF. ENDLOOP. ENDMETHOD.
METHOD setInitialStatus. READ ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking FIELDS ( booking_status ) WITH CORRESPONDING #( keys ) RESULT DATA(bookings).
MODIFY ENTITIES OF zi_flightbooking IN LOCAL MODE ENTITY FlightBooking UPDATE FIELDS ( booking_status ) WITH VALUE #( FOR booking IN bookings WHERE ( booking_status IS INITIAL ) ( %tky = booking-%tky booking_status = 'O' ) ). ENDMETHOD.ENDCLASS.Limitaciones Actuales
El CDS Pattern es potente, pero tiene restricciones (estado febrero 2026):
ENUMs no soportados directamente
" ❌ NO funciona en Table Entitiesbooking_status : zbooking_status_enum;
" ✅ Solución alternativa: campo CHAR con Value Helpbooking_status : abap.char(1);Los valores Enum deben proporcionarse a través de un Value Help separado o anotación CDS.
Draft Handling limitado
" ❌ Draft requiere stack RAP clásico con Projection Viewwith draft;
" ✅ En CDS Pattern: Solo posible sin Draft" Table Entity no soporta draft tablePara funcionalidad Draft, todavía necesita la estructura RAP clásica con Interface View y Projection View.
Sin campos calculados
" ❌ NO es posible en Table Entitycalculated_field : abap.char(10) = concat(carrier_id, connection_id);
" ✅ CDS View clásicadefine view entity ZI_FlightBooking as select from zflight_book { key booking_id, concat(carrier_id, connection_id) as FlightNumber}Sin asociaciones a otros Table Entities
" ❌ Table Entity no puede definir asociacionesassociation [1..1] to zi_customer as _Customer;
" ✅ Solución alternativa: CDS View separada para asociaciones¿Cuándo usar qué patrón?
CDS Pattern recomendado
- Aplicaciones CRUD simples sin relaciones complejas
- Mantenimiento de datos maestros (Clientes, Productos, Configuraciones)
- Prototipos rápidos y MVPs
- Aplicaciones sin requisito de Draft
- Entidades independientes sin jerarquías
Stack RAP Clásico recomendado
- Business Objects complejos con jerarquías Parent-Child
- Draft Handling requerido
- Campos calculados necesarios en la View
- Aliases de campo para mejor legibilidad
- Asociaciones entre Entities
- Diferentes Projections para distintas apps
Migración: De CDS Pattern a Stack Clásico
Si los requisitos crecen, puede migrar:
" 1. Table Entity permanece como tabla de base de datos" (Renombrar a ztable_flightbooking)
" 2. Crear nueva Interface CDS Viewdefine root view entity ZI_FlightBooking as select from ztable_flightbooking{ key booking_id as BookingId, " ... más campos con aliases}
" 3. Ajustar Behavior Definitiondefine behavior for ZI_FlightBookingpersistent table ztable_flightbooking" ...Conclusión
El RAP CDS Pattern reduce significativamente el esfuerzo de desarrollo para aplicaciones RAP simples:
| Criterio | CDS Pattern | Clásico |
|---|---|---|
| Objetos de desarrollo | 3-4 | 5-7 |
| Tiempo de aprendizaje | Más corto | Más largo |
| Flexibilidad | Estándar | Máxima |
| Soporte Draft | No | Sí |
| Asociaciones | Limitadas | Completas |
Para principiantes y aplicaciones CRUD simples, el CDS Pattern es el camino más rápido hacia una aplicación Fiori funcional. Con requisitos crecientes, se puede migrar al stack clásico.
Artículos relacionados: Fundamentos de RAP para el patrón clásico, Tablas en ABAP Cloud para definiciones de tablas, RAP Managed vs Unmanaged para la decisión de arquitectura y CDS Views para modelos de datos complejos.