Em princípio, os programas ABAP trabalham com dados de programas locais, que residem na sessão interna dos programas, os dados vivem somente enquanto seu contexto existe, estes tipos de dados são chamados de Transient e existem dentro de objetos de dados do ABAP. Os dados que podem ser preservados além do tempo de execução do programa é conhecido como persistente.
Em uma aplicação orientada a objeto ideal, os dados ocorrem apenas como os atributos de objetos, objetos são uma agregação de funções, nos métodos e de dados nos atributos. A descrição de um objeto, ou seja, a classe, ocorre persistentemente como um pedaço de código-fonte. Isto significa que linguagens orientadas a objeto persistem dados contidos nos atributos dos objetos, que podem ser manipulados através de seus métodos. Tecnicamente falando em uma linguagem orientada a objetos, os objetos contem dados Transients e através de serviços como o SAP Persistence Service podemos utilizar o recurso de mapeamento para preenche a lacuna entre a visão do banco de dados relacional e da visão orientada a objeto, ou seja podemos mapear um atributo que contem dados e liga-lo a um campo em uma tabela transparente.
Podemos identificar cada instancia do objeto utilizando um identificador único global ou GUID (Globally Unique IDentifier) que é um tipo especial de identificador utilizado em aplicações de software para providenciar um número de referência que será único em qualquer contexto (por isso é “Universal”) como, por exemplo, em uma definição de referência interna para um tipo de ponto de acesso em uma aplicação de software ou para a criação de chaves únicas em um banco de dados.
O serviço de persistência permite que o programador ABAP trabalhe com dados de bancos de dados relacionais de forma orientada a objetos, este serviço pode ser comparado a vários outros tipos de frameworks conhecidos como ORM (Object-relational mapping) é uma técnica de desenvolvimento utilizada para reduzir a impedância da programação orientada aos objetos utilizando bancos de dados relacionais. As tabelas do banco de dados são representadas através de classes e os registros de cada tabela são representados como instâncias das classes correspondentes.
SAP Persistence Service: Serviço de Persistência
Usando o Serviço de Persistência com Web Dynpro
1 – Crie uma tabela transparente chamada ZPARTICIPANTE, utilize a imagem abaixo para os tipos de campos:
2 – No Class Builder, na transação SE24 crie uma nova classe do tipo persistente chamada ZCL_PARTICIPANTE:
3 – Note que temos uma classe com algumas interfaces implementadas. No menu Goto escolha Persistence Representant:
4 – Escolha a tabela transparente criada acima para o mapeamento do objeto:
5 – Selecione os campos do dicionário de dados na parte inferior e os insira na parte superior, no qual definirá o mapeamento relacional para o objeto:
6 – Com o mapeamento finalizado salve e volte para a edição da classe:
7 – Como você pode notar os atributos e métodos necessários para o mapeamento objeto relacional foram criados automaticamente, salve e ative a classe:
8 – Crie um novo componente Web Dynpro e utilize os elementos de acordo a cada campo na tela, crie um método para o botão e um método de persistência de acordo com os códigos abaixo:
9 – Salve, ative, crie e teste sua aplicação. Preencha os dados na pagina web e os envie, eles serão automaticamente persistidos no banco de dados utilizado pelo sistema:
10 – Você pode conferir os dados persistidos no bando através do Data Browser na transação SE16:
Exemplo:
Neste exemplo persistimos dados através do serviço de persistência SAP que utiliza um mapeamento objeto relacional, que pode ser considerado equivalente aos frameworks ORM de outras linguagens de programação como o Rails (Ruby), Hibernate (Java), EF (C#) e ORM Django (Python) entre vários outros.
ABAP
Evento – ONACTIONACAO_BOTAO_ENVIAR
method ONACTIONACAO_BOTAO_ENVIAR . * // Retorna campos do contexto da View DATA lo_nd_usuario_controler TYPE REF TO if_wd_context_node. DATA lo_el_usuario_controler TYPE REF TO if_wd_context_element. DATA ls_usuario_controler TYPE wd_this->Element_usuario_controler. DATA lv_cargo TYPE wd_this->Element_usuario_controler-cargo. * // Recupera node controller lo_nd_usuario_controler = wd_context->get_child_node( name = wd_this->wdctx_usuario_controler ). * // Recupera elemento via lead selection lo_el_usuario_controler = lo_nd_usuario_controler->get_element( ). * // Recupera atributo lo_el_usuario_controler->get_attribute( EXPORTING name = `CARGO` IMPORTING value = lv_cargo ). * // Define objetos Regex DATA: regex TYPE REF TO cl_abap_regex, matcher TYPE REF TO cl_abap_matcher. * Cria objeto Regex e define Pattern CREATE OBJECT regex EXPORTING pattern = '[a-zA-Z]+'. * // Verifica valot do elemento contra o Pattern matcher = regex->create_matcher( text = lv_cargo ). * // Verifca Pattern IF matcher->match( ) NE 'X'. * // Define menssagem data lo_api_controller type ref to if_wd_controller. data lo_message_manager type ref to if_wd_message_manager. lo_api_controller ?= wd_This->Wd_Get_Api( ). * // Chama método de menssagem CALL METHOD lo_api_controller->GET_MESSAGE_MANAGER RECEIVING MESSAGE_MANAGER = lo_message_manager. * // Exibe mensagem CALL METHOD lo_message_manager->REPORT_MESSAGE EXPORTING MESSAGE_TEXT = 'Cargo é exclusivamente um campo alphanumérico' CANCEL_NAVIGATION = ABAP_TRUE. ENDIF. * // Gravar dados wd_this->ONGRAVAR( ). endmethod.
Método – ONGRAVAR
method ONGRAVAR . * // Recupera dados do controlador DATA lo_nd_usuario_controler TYPE REF TO if_wd_context_node. DATA lo_el_usuario_controler TYPE REF TO if_wd_context_element. DATA ls_usuario_controler TYPE wd_this->Element_usuario_controler. DATA lv_usuario_login TYPE wd_this->Element_usuario_controler-usuario_login. lo_nd_usuario_controler = wd_context->get_child_node( name = wd_this->wdctx_usuario_controler ). lo_el_usuario_controler = lo_nd_usuario_controler->get_element( ). * // Recupera Nome lo_el_usuario_controler->get_attribute( EXPORTING name = `USUARIO_LOGIN` IMPORTING value = lv_usuario_login ). * // Recupera Sobrenome DATA lv_sobrenome TYPE wd_this->Element_usuario_controler-sobrenome. lo_nd_usuario_controler = wd_context->get_child_node( name = wd_this->wdctx_usuario_controler ). lo_el_usuario_controler = lo_nd_usuario_controler->get_element( ). lo_el_usuario_controler->get_attribute( EXPORTING name = `SOBRENOME` IMPORTING value = lv_sobrenome ). * // Recupera Cargo DATA lv_cargo TYPE wd_this->Element_usuario_controler-cargo. lo_nd_usuario_controler = wd_context->get_child_node( name = wd_this->wdctx_usuario_controler ). lo_el_usuario_controler = lo_nd_usuario_controler->get_element( ). lo_el_usuario_controler->get_attribute( EXPORTING name = `CARGO` IMPORTING value = lv_cargo ). * // Recupera Salario DATA lv_salario TYPE wd_this->Element_usuario_controler-salario. lo_nd_usuario_controler = wd_context->get_child_node( name = wd_this->wdctx_usuario_controler ). lo_el_usuario_controler = lo_nd_usuario_controler->get_element( ). lo_el_usuario_controler->get_attribute( EXPORTING name = `SALARIO` IMPORTING value = lv_salario ). * // Recupera Data DATA lv_data TYPE wd_this->Element_usuario_controler-data. lo_nd_usuario_controler = wd_context->get_child_node( name = wd_this->wdctx_usuario_controler ). lo_el_usuario_controler = lo_nd_usuario_controler->get_element( ). lo_el_usuario_controler->get_attribute( EXPORTING name = `DATA` IMPORTING value = lv_data ). * // Recupera Genero DATA lv_genero TYPE wd_this->Element_usuario_controler-genero. lo_nd_usuario_controler = wd_context->get_child_node( name = wd_this->wdctx_usuario_controler ). lo_el_usuario_controler = lo_nd_usuario_controler->get_element( ). lo_el_usuario_controler->get_attribute( EXPORTING name = `GENERO` IMPORTING value = lv_genero ). * // Recupera Ativo DATA lv_ativo TYPE wd_this->Element_usuario_controler-ativo. lo_nd_usuario_controler = wd_context->get_child_node( name = wd_this->wdctx_usuario_controler ). lo_el_usuario_controler = lo_nd_usuario_controler->get_element( ). lo_el_usuario_controler->get_attribute( EXPORTING name = `ATIVO` IMPORTING value = lv_ativo ). * // Recupera Observacao DATA lv_observacao TYPE wd_this->Element_usuario_controler-observacao. lo_nd_usuario_controler = wd_context->get_child_node( name = wd_this->wdctx_usuario_controler ). lo_el_usuario_controler = lo_nd_usuario_controler->get_element( ). lo_el_usuario_controler->get_attribute( EXPORTING name = `OBSERVACAO` IMPORTING value = lv_observacao ). * // Declara variáveis DATA : guid TYPE zGuid, nome TYPE ZNome, sobrenome TYPE ZSobrenome, cargo TYPE ZCargo, salario TYPE Zsal, data_adm TYPE Zdata, genero TYPE ZGenero, ativo TYPE Zativo, observacao TYPE ZObservacao. * // Alimenta dados. nome = LV_USUARIO_LOGIN. sobrenome = LV_SOBRENOME. cargo = LV_CARGO. salario = LV_SALARIO. data_adm = LV_DATA. genero = LV_GENERO. ativo = LV_ATIVO. observacao = LV_OBSERVACAO. * // Gera GUID CALL FUNCTION 'GUID_CREATE' IMPORTING ev_guid_16 = guid. * // Cria persistencia * // Declara classe Actor e Persistencia DATA: agente TYPE REF TO ZCA_PARTICIPANTE, participante TYPE REF TO ZCL_PARTICIPANTE. * // Cria agente da classe actor AGENTE = ZCA_PARTICIPANTE=>AGENT. * // cria persistencia try. participante = AGENTE->CREATE_PERSISTENT( guid ). catch CX_OS_OBJECT_EXISTING. ENDTRY. * // Alimenta objeto de persistencia PARTICIPANTE->SET_NOME( NOME ). PARTICIPANTE->SET_SOBRENOME( SOBRENOME ). PARTICIPANTE->SET_CARGO( CARGO ). PARTICIPANTE->SET_DATA( DATA_ADM ). PARTICIPANTE->SET_SALARIO( SALARIO ). PARTICIPANTE->SET_GENERO( GENERO ). PARTICIPANTE->SET_ATIVO( ATIVO ). PARTICIPANTE->SET_OBSERVACAO( OBSERVACAO ). * // Grava e finaliza persistencia TRY. COMMIT WORK. * // Exibe mensagem data lo_api_controller type ref to if_wd_controller. data lo_message_manager type ref to if_wd_message_manager. lo_api_controller ?= wd_This->Wd_Get_Api( ). * // Chama método de menssagem CALL METHOD lo_api_controller->GET_MESSAGE_MANAGER RECEIVING MESSAGE_MANAGER = lo_message_manager. * // Exibe mensagem CALL METHOD lo_message_manager->REPORT_SUCCESS EXPORTING MESSAGE_TEXT = 'Dados Inseridos com Sucesso'. ENDTRY. endmethod.