CDS Abstract
Uma view que não "vê" nada?
Todo desenvolvedor ABAP aprende CDS pelo caminho óbvio: view lê tabela, view lê view, view junta, calcula, expõe. Aí um dia você abre um exemplo de RAP e encontra isto:
define abstract entity ZD_Reject_Reason
{
ReasonCode : abap.char(2);
ReasonText : abap.char(80);
}Cadê o as select from? Cadê a tabela? Não tem — e é de propósito. Uma abstract entity é uma CDS que existe só para definir uma estrutura de dados, sem fonte, sem persistência, sem consulta. A documentação chama de entidade transiente: na ativação, só o metadado é criado — nenhum objeto nasce no banco de dados, e ela não pode ser acessada via ABAP SQL.
Se você vem do mundo clássico, a analogia que destrava tudo: abstract entity está para o CDS assim como a estrutura da SE11 está para o DDIC. É um "tipo estruturado" — só que definido em CDS, com anotações, associações e tudo que a linguagem oferece. Muita gente passa anos sem usar simplesmente porque nunca precisou declarar um tipo no mundo CDS. Até o dia em que precisa — e no RAP, esse dia chega rápido.
O que pode e o que não pode
Abstract entity PODE | Abstract entity NÃO PODE |
|---|---|
Definir elementos tipados (built-in types, data elements, simple types, enums) | Ter fonte de dados ( |
Ter anotações no cabeçalho e nos elementos ( | Ser usada como data source de outra CDS |
Declarar associações (publicadas, mas sem virar join) | Ser lida via |
Ter parâmetros de entrada opcionais | Guardar dados — não existe objeto no banco |
Ser usada como tipo global no ABAP ( | Aparecer como estrutura clássica nas ferramentas da SE11 |
Receber metadata extensions ( | — |
E sim, ela vira tipo ABAP de verdade:
DATA ls_reason TYPE ZD_Reject_Reason. " funciona: tipo estruturado global
ls_reason-ReasonCode = 'P2'.
ls_reason-ReasonText = 'Fora da política de compras'.
" mas isto NÃO compila:
" SELECT * FROM ZD_Reject_Reason ... " abstract entity não é fonte de dadosEmprego nº 1: parâmetro de action (o popup do Fiori)
O uso mais frequente de longe. No RAP, quando uma action precisa de informações do usuário, o parâmetro é tipado por uma abstract entity — e o Fiori Elements gera o popup automaticamente a partir dela, campo a campo, com os labels vindos das anotações:
@EndUserText.label: 'Motivo da rejeição'
define abstract entity ZD_Reject_Reason
{
@EndUserText.label: 'Código do motivo'
ReasonCode : abap.char(2);
@EndUserText.label: 'Justificativa'
ReasonText : abap.char(80);
}" na behavior definition:
action reject parameter ZD_Reject_Reason result [1] $self;
" na implementação, os valores chegam via %param:
DATA(lv_code) = key-%param-ReasonCode.Cada elemento da abstract entity vira um campo do diálogo. Você desenha a "tela" do popup declarando uma estrutura — nada de layout manual.
Emprego nº 2: resultado de action ou function
Quando o retorno não é a própria entidade ($self) nem outra entidade do modelo, a abstract entity tipa o resultado. O clássico é a simulação — a resposta é uma estrutura calculada que não existe persistida em lugar nenhum:
@EndUserText.label: 'Resultado da simulação de imposto'
define abstract entity ZD_Tax_Simulation
{
NetAmount : abap.dec(15,2);
TaxAmount : abap.dec(15,2);
GrossAmount : abap.dec(15,2);
}function simulateTax result [1] ZD_Tax_Simulation;Por que não usar um elemento DDIC direto como parâmetro? Até funciona em alguns casos — mas a recomendação oficial é usar apenas CDS abstract entities como parâmetros BDEF. O motivo é contrato: a abstract entity é versionável, extensível, carrega labels para a UI e evolui sem quebrar a assinatura. Um tipo solto não oferece nada disso.
Emprego nº 3: payload de business event
Mesma lógica no mundo dos eventos: o conteúdo que viaja num RAP Business Event é tipado por uma abstract entity. As chaves da entidade vão sempre; a abstract entity define os campos extras do payload:
define abstract entity ZD_Travel_Booked
{
TravelId : /dmo/travel_id;
CustomerId : /dmo/customer_id;
TotalPrice : /dmo/total_price;
Currency : /dmo/currency_code;
}event travelBooked parameter ZD_Travel_Booked;Aqui a abstract entity assume o papel mais nobre dela: é o contrato público entre o seu sistema e todos os consumidores do evento. Mudou a estrutura, mudou o contrato — trate com o mesmo cuidado de uma API.
Emprego nº 4: parâmetros deep (estruturas hierárquicas)
Parâmetro flat (estrutura plana) resolve 90% dos casos. Mas e quando a pergunta em si é hierárquica — "simule este documento com estes itens"? Aí entram as abstract entities em árvore: uma root abstract entity com composition para abstract entities filhas, amarradas por uma abstract behavior definition (implementação abstract, com with hierarchy):
define root abstract entity ZD_Doc_Simulation
{
DocType : abap.char(2);
_Items : composition [0..*] of ZD_Doc_Simulation_Item;
}
define abstract entity ZD_Doc_Simulation_Item
{
Material : matnr;
Quantity : abap.quan(13,3);
_Doc : association to parent ZD_Doc_Simulation;
}" abstract behavior definition (tipo de implementação: abstract)
abstract;
with hierarchy;
define behavior for ZD_Doc_Simulation
{
association _Items;
}
define behavior for ZD_Doc_Simulation_Item
{
association _Doc;
}" e na BDEF do BO, o parâmetro ganha a palavra-chave deep:
action simulateDocument deep parameter ZD_Doc_Simulation result [1] ZD_Tax_Simulation;Pegadinha de exposição: OData V2 só aceita parâmetros flat. Operação com parâmetro deep num serviço V2 gera erro no service binding. Parâmetro deep pede OData V4.
Emprego nº 5: tipo estruturado global no ABAP Cloud
Fora do RAP, a abstract entity é a resposta moderna para "onde declaro minha estrutura global?". No ABAP Cloud/Clean Core, ela ocupa o espaço da estrutura DDIC clássica: um tipo global, referenciável via TYPE em qualquer classe, avaliável via RTTI — e definido em CDS, com anotações que ferramentas e frameworks (como o SADL) conseguem interpretar. A documentação é explícita: abstract entities servem como tipos cujos atributos vão além das estruturas regulares do DDIC.
Emprego nº 6: proxy de serviço OData remoto (Service Consumption Model)
Um uso que aparece "pronto" sem você pedir: ao criar um Service Consumption Model para consumir um serviço OData externo (via arquivo $metadata no ADT), o wizard gera abstract entities representando os entity types do serviço remoto — a estrutura tipada dos dados que virão de fora. E tem um bônus: a sintaxe da abstract entity é tão parecida com a de uma custom entity que a própria SAP ensina a reaproveitar o DDL gerado como base ao construir a custom entity que expõe aqueles dados remotos.
(Observação de contexto: a versão 2 do Service Consumption Model para OData mudou a abordagem — gera uma única classe com definições de tipos em vez de uma abstract entity por entity type, justamente para reduzir a quantidade de artefatos. Mas o padrão v1, com abstract entities, segue presente em muito sistema por aí.)
Abstract entity vs. os parentes: qual é qual?
Artefato | Tem dados? | De onde vêm? | Para que serve |
|---|---|---|---|
View entity | Sim | Banco (select from) | Modelo de dados, consultas, exposição |
Custom entity | Sim (em runtime) | Classe ABAP (query provider) | Expor dados que não estão em tabela local (API remota, cálculo) |
Abstract entity | Nunca | Lugar nenhum | Definir tipo/estrutura: parâmetros, payloads, contratos |
Estrutura DDIC (SE11) | Nunca | Lugar nenhum | O ancestral clássico — sem anotações CDS, sem associações |
A confusão mais comum é com a custom entity, porque a sintaxe é quase igual. O critério é um só: custom entity entrega dados em runtime (via classe que implementa a query); abstract entity jamais entrega dado algum — ela é só o molde.
Boas práticas
Uma abstract entity por propósito. Não crie a "estrutura genérica de parâmetros" do projeto — cada action/evento com seu contrato próprio evolui sem efeito colateral.
Anote tudo com
@EndUserText.label— no popup do Fiori, cada elemento vira campo, e o label é o que o usuário lê.Prefira data elements a built-in types quando existirem: herdam semântica, ajuda de pesquisa e descrições.
Enxuta é melhor: em payload de evento e parâmetro de action, cada campo a mais é acoplamento a mais. Na dúvida, mande a chave e deixe o consumidor buscar o resto.
Adote uma convenção de nomes que diferencie abstract entities do resto do modelo (nos exemplos da SAP você verá o padrão
/dmo/a_*; em projetos, prefixos comoZA_/ZD_são comuns) — bater o olho e saber que é um tipo, não uma view, economiza tempo de todo mundo.Trate como contrato: se a abstract entity tipa um evento ou uma API, mudança nela é mudança de interface pública. Versione via event binding / novo artefato em vez de alterar no lugar.
Perguntas frequentes
Abstract entity aparece na SE11?
Não — nenhuma estrutura DDIC clássica visível nas ferramentas é criada. Ela vive no namespace dos tipos do dicionário e dos tipos globais da class library, mas o artefato é CDS puro, gerenciado no ADT.
Consigo dar SELECT numa abstract entity?
Não. Ela não pode ser fonte de dados nem em ABAP SQL nem em outras CDS. Se você precisa de SELECT, o artefato certo é uma view entity (dados no banco) ou uma custom entity (dados via classe).
Preciso declarar campo key?
O key é permitido na definição dos elementos, mas como não há dados nem acesso via SQL, ele tem papel estrutural/semântico (por exemplo, em cenários hierárquicos e na interpretação por frameworks) — não existe "chave primária de banco" aqui.
Qual a diferença para uma estrutura DDIC da SE11?
Funcionalmente ambas são "tipos sem dados", mas a abstract entity é CDS: aceita anotações (labels, semântica), associações, parâmetros de entrada, metadata extensions e é interpretável por frameworks como o RAP e o SADL. No ABAP Cloud, é o caminho padrão.
Abstract entity pode ter associação? Para quê, se não tem dados?
Pode — a associação é publicada como metadado (mas nunca vira join nem path expression executável). Serve para expressar relações estruturais, como as composições dos parâmetros deep e informações que frameworks avaliam.
E a abstract behavior definition, é obrigatória?
Só no cenário de parâmetro deep: é ela (implementação abstract, with hierarchy) que amarra a árvore de abstract entities num tipo hierárquico utilizável como parâmetro. Para parâmetros flat, payloads de evento e results, a abstract entity sozinha basta.
Conclusão
Abstract entity é o artefato mais simples do CDS — e talvez por isso o mais mal explicado: não tem dados, não tem consulta, não tem mistério. Ela é o tipo estruturado do mundo CDS: o molde dos parâmetros de actions e functions, o contrato dos payloads de eventos, a hierarquia dos parâmetros deep, o tipo global do ABAP Cloud e o proxy dos serviços consumidos. Se você nunca usou, provavelmente é porque nunca tinha criado uma action com popup ou um evento com payload — e agora que os posts de actions, functions e events estão aí, a desculpa acabou.
Referências oficiais
Comentários 0
Ainda sem comentários
Seja o primeiro a comentar este artigo.
Entre na conversa
Faça login para deixar seu comentário neste artigo.