O Open SQL consiste em um conjunto de instruções ABAP que executam operações no banco de dados central no SAP Web AS ABAP. Os resultados das operações e as mensagens de erro são independentes do sistema de base de dados em uso. Open SQL proporciona assim uma sintaxe e a semântica uniforme para todos os sistemas de base de dados suportadas pela SAP. Programas ABAP que usam apenas instruções Open SQL iram funcionar em qualquer sistema SAP, independentemente do sistema de banco de dados em uso.
O Open SQL fornece uma solução moderna e inteligente para persistir dados nos sistemas SAP, no entanto Open SQL é baseado no paradigma de programação declarativa da linguagem SQL e utiliza os tipos de dados e os Data Objects que definem os tipos de campos do sistema SAP, além de também utilizar o dicionário de dados ABAP para manipular dados. Este modelo apesar de ser eficiente e rápido, se utilizado dentro das melhores praticas, não tratam os dados como objetos assim como os frameworks ORM mais modernos usados atualmente nas linguagens orientadas a objeto como o Hibernate, Rails , Entity Framework e vários outros.
A desvantagem é que o ABAP com o Open SQL não proporciona um modo simples a manipulação dos dados completamente orientados a objetos, não podemos manipular objetos e persisti-los do mesmo modo que os frameworks ORM nos proporcionam e nem utilizar recursos de identificadores automáticos que manipulam objetos do banco de dados como tipos de auto incrementos ou sequencias, mas podemos utilizar alguns Design Patterns para adaptar esta funcionalidade, o único inconveniente é que este tipo de programação pode gerar margem há uma mistura de paradigmas que pode ocasionar um código de baixa qualidade caso não utilizado conforme seus padrões. Por outro lado os sistemas SAP rodam em um ambiente pré estabelecido e já possuem todos os recursos necessários para que você possa manipular e persistir dados facilmente e você só sentirá falta dos recursos dos modernos dos frameworks ORM apenas se você já os utiliza em outras linguagens de programação.
ABAP: Open SQL
Obs: A SAP nos proporciona um framework de persistência ORM para trabalhar sobre o OpenSQL, veremos sobre estas classes mais adiante.
Persistence: Conceitos de Persistência
Persistindo Dados Com Web Dynpro e Open SQL
Os códigos a seguir utilizam os métodos da View de um modo simples para que seja de fácil entendimento, a manipulação de dados não estão escritos sob nenhum Design Pattern especifico além do MVC proporcionado pelo Web Dynpro.
1 – Crie uma nova tabela transparente chama ZPARTICIPANTE, crie seus tipos, utilize a figura abaixo para detalhes:
2 – Defina o tipo de tabela e a quantidade de registros previstos para a tabela:
3 – Quando finalizar ative sua tabela:
4 – O dicionário de dados e o Open SQL não nos proporcionam nenhum tipo de recurso para manipulação de IDs automáticos, ou objetos do banco de dados, já que não possuímos acesso diretamente a ele. No entanto utilizaremos um objeto chamado NUMBER RANGE.
Numer Range: Number Range Object Types
Entre na transação SNRO e crie um novo objeto chamado ZID_PAR:
5 – Em Number Length Domain use, NUM10 e em Warning % use o valor 5 ou o valor de porcentagem que deseja receber avisos quando a faixa estiver chegando ao seu limite. Salve.
6 – Clique em Intervals e crie um novo intervalo:
7 – Adicione a faixa de valores desejados que serão utilizados para criar seus identificadores:
8 – Crie um novo componente Web Dynpro para os dados da tabela, crie seus atributos no controlador e os use na View. Crie um evento para o botão e um método para gravar dos dados na tabela transparente:
9 – Ative seu componente Web Dynpro, e teste sua aplicação:
10 – Abra a transação SE16 para acessar o navegador de dados do Netweaver e verifique os dados gravados com sucesso:
Exemplo:
Neste exemplo criamos uma tabela transparente e persistimos dados no banco de dados corrente através do Open SQL.
ABAP
Método Botão – 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 Gravação – 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 : 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. * // Recupera numero auto-incremento para o ID DATA id_participante TYPE I. CALL FUNCTION 'NUMBER_GET_NEXT' EXPORTING nr_range_nr = '1' object = 'ZID_PAR' IMPORTING NUMBER = ID_PARTICIPANTE EXCEPTIONS INTERVAL_NOT_FOUND = 1 NUMBER_RANGE_NOT_INTERN = 2 OBJECT_NOT_FOUND = 3 QUANTITY_IS_0 = 4 QUANTITY_IS_NOT_1 = 5 INTERVAL_OVERFLOW = 6 BUFFER_OVERFLOW = 7 OTHERS = 8. * // Cria Set de dados DATA participante TYPE ZPARTICIPANTE. PARTICIPANTE-ID_PART = ID_PARTICIPANTE. PARTICIPANTE-NOME = NOME. PARTICIPANTE-SOBRENOME = SOBRENOME. PARTICIPANTE-CARGO = CARGO. PARTICIPANTE-DATA = DATA_ADM. PARTICIPANTE-GENERO = GENERO. PARTICIPANTE-ATIVO = ATIVO. PARTICIPANTE-OBSERVACAO = OBSERVACAO. * // Insere dados na tabela INSERT INTO ZPARTICIPANTE VALUES PARTICIPANTE. IF SY-SUBRC = 0. * 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_SUCCESS EXPORTING MESSAGE_TEXT = 'Dados Inseridos com Sucesso'. ENDIF. endmethod.