RAP desde cero · Lección 2 de 6
Modelo de datos en RAP: tablas, CDS View Entity y asociaciones
Crea las tablas de una biblioteca, carga datos de prueba y define la Root View Entity con sus asociaciones: la base de cualquier objeto de negocio RAP.
Toda aplicación RAP se construye por capas, de abajo hacia arriba:
- Datos: tablas de base de datos y CDS View Entities (esta lección).
- Proyección y servicio: lo que se expone hacia fuera (lección 3).
- Comportamiento: qué se puede hacer con los datos y con qué reglas (lección 4).
Seguimos con la biblioteca de la lección anterior: autores y libros.
1. Las tablas
En ADT: New → Other ABAP Repository Object → Dictionary → Database Table.
Autores, una tabla sencilla de consulta:
@EndUserText.label : 'Biblioteca: autores'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zlib_author {
key client : abap.clnt not null;
key author_id : abap.numc(6) not null;
name : abap.char(60);
country : abap.char(2);
}
Libros, que será el objeto de negocio RAP:
@EndUserText.label : 'Biblioteca: libros'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zlib_book {
key client : abap.clnt not null;
key book_uuid : sysuuid_x16 not null;
book_id : abap.numc(8);
title : abap.char(80);
author_id : abap.numc(6);
pages : abap.int4;
isbn : abap.char(17);
rating : abap.int1;
@Semantics.amount.currencyCode : 'zlib_book.currency_code'
price : abap.curr(11,2);
currency_code : abap.cuky;
local_created_by : abp_creation_user;
local_created_at : abp_creation_tstmpl;
local_last_changed_by : abp_locinst_lastchange_user;
local_last_changed_at : abp_locinst_lastchange_tstmpl;
last_changed_at : abp_lastchange_tstmpl;
}
Fíjate en tres cosas:
- Clave técnica
book_uuid: RAP la podrá generar sola al crear un libro (managed numbering). El número visible para el usuario esbook_id, la clave semántica. @Semantics.amount.currencyCode: todo campoCURRnecesita su campo de moneda de referencia.- Los cinco campos de administración (
local_created_by…last_changed_at) usan los elementos de datosabp_*. RAP los rellena solo y los necesitará para el bloqueo optimista (ETag) y, más adelante, para el modo draft. Ponlos desde el principio.
2. Datos de prueba
Una clase de consola para llenar las tablas. Ejecútala con F9 cada vez que quieras volver a empezar:
CLASS zcl_lib_fill_data DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
ENDCLASS.
CLASS zcl_lib_fill_data IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA authors TYPE STANDARD TABLE OF zlib_author WITH EMPTY KEY.
DATA books TYPE STANDARD TABLE OF zlib_book WITH EMPTY KEY.
DELETE FROM zlib_book.
DELETE FROM zlib_author.
authors = VALUE #(
( author_id = '000001' name = 'Ana Rojas' country = 'CL' )
( author_id = '000002' name = 'Carlos Soto' country = 'AR' )
( author_id = '000003' name = 'Elena Vidal' country = 'ES' ) ).
books = VALUE #(
( book_id = '00000010' title = 'Aves del sur' author_id = '000001' pages = 320
isbn = '978-0-0000-0010-1' rating = 4 price = '24.90' currency_code = 'USD' )
( book_id = '00000011' title = 'Ríos de montaña' author_id = '000001' pages = 180
isbn = '978-0-0000-0011-1' rating = 5 price = '18.50' currency_code = 'USD' )
( book_id = '00000012' title = 'El último tren' author_id = '000002' pages = 410
isbn = '978-0-0000-0012-1' rating = 3 price = '21.00' currency_code = 'USD' )
( book_id = '00000013' title = 'Cuentos de invierno' author_id = '000003' pages = 120
isbn = '978-0-0000-0013-1' rating = 4 price = '12.00' currency_code = 'EUR' ) ).
LOOP AT books ASSIGNING FIELD-SYMBOL(<book>).
TRY.
<book>-book_uuid = cl_system_uuid=>create_uuid_x16_static( ).
CATCH cx_uuid_error.
out->write( 'No se pudo generar el UUID' ).
RETURN.
ENDTRY.
ENDLOOP.
INSERT zlib_author FROM TABLE @authors.
INSERT zlib_book FROM TABLE @books.
out->write( |{ lines( authors ) } autores y { lines( books ) } libros cargados| ).
ENDMETHOD.
ENDCLASS.
Es la misma sintaxis VALUE #( … ) de la lección 1, ahora con los tipos de las tablas reales. El campo client no se informa: el sistema lo pone solo.
3. La vista de autores
Una CDS View Entity sencilla sobre zlib_author. Será el destino de una asociación:
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Biblioteca: autores'
define view entity ZI_LibAuthor
as select from zlib_author
{
key author_id as AuthorId,
name as Name,
country as Country
}
Los nombres de los campos pasan de snake_case (tabla) a CamelCase (CDS). Es la convención que verás en todo el código RAP.
4. La Root View Entity del libro
La entidad raíz es la cabeza del objeto de negocio: todo lo demás (comportamiento, proyección, servicio) cuelga de ella. Por convención lleva el prefijo R_; la proyección llevará C_ y una interfaz reutilizable, I_.
@AccessControl.authorizationCheck: #NOT_REQUIRED
@Metadata.allowExtensions: true
@EndUserText.label: 'Biblioteca: libros'
define root view entity ZR_LibBook
as select from zlib_book
association [0..1] to ZI_LibAuthor as _Author
on $projection.AuthorId = _Author.AuthorId
association [0..1] to I_Currency as _Currency
on $projection.CurrencyCode = _Currency.Currency
{
key book_uuid as BookUuid,
book_id as BookId,
title as Title,
author_id as AuthorId,
pages as Pages,
isbn as Isbn,
rating as Rating,
@Semantics.amount.currencyCode: 'CurrencyCode'
price as Price,
@Consumption.valueHelpDefinition: [ {
entity.name: 'I_CurrencyStdVH',
entity.element: 'Currency',
useForValidation: true
} ]
currency_code as CurrencyCode,
@Semantics.user.createdBy: true
local_created_by as LocalCreatedBy,
@Semantics.systemDateTime.createdAt: true
local_created_at as LocalCreatedAt,
@Semantics.user.localInstanceLastChangedBy: true
local_last_changed_by as LocalLastChangedBy,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
local_last_changed_at as LocalLastChangedAt,
@Semantics.systemDateTime.lastChangedAt: true
last_changed_at as LastChangedAt,
// Asociaciones públicas
_Author,
_Currency
}
Las asociaciones
association [0..1] to ZI_LibAuthor as _Author on …declara la relación: cada libro tiene como mucho un autor. El prefijo_es convención.$projection.AuthorIdse refiere al campo tal como se llama en esta vista (AuthorId), no en la tabla.- Una asociación es perezosa: no se hace ningún JOIN hasta que alguien la usa (por ejemplo,
_Author.Name).
Error típico: declarar la asociación y olvidar listarla al final (
_Author, _Currency). La asociación existe, pero nadie puede usarla desde fuera de la vista.
Ayuda de búsqueda en la moneda
@Consumption.valueHelpDefinition conecta el campo con I_CurrencyStdVH, una vista estándar de ayuda de búsqueda. Con useForValidation: true, la interfaz Fiori también rechazará monedas que no existan.
Las anotaciones @Semantics de administración
Le dicen a RAP qué campo es «creado por», «modificado el», etc. Con ellas, el framework los rellenará automáticamente cuando añadamos el comportamiento.
5. Comprueba el resultado
Activa todo (Ctrl+Shift+F3), abre ZR_LibBook y pulsa F8 (Data Preview):
- deberías ver los cuatro libros;
- con clic derecho en una fila → Follow Association →
_Author, navegas al autor del libro.
Si ves los datos y la navegación funciona, el modelo de datos está listo. En la próxima lección lo exponemos como servicio OData y lo vemos en una aplicación Fiori sin escribir una línea de UI5.
Recibe los nuevos tutoriales
Un correo cuando publique algo nuevo. Sin spam; te das de baja cuando quieras.
Te enviaré un correo para confirmar la suscripción. Datos tratados según la política de privacidad.