DB V2 - cenários de uso

Saiba mais sobre como você pode usar o componente via Kerberos em alguns cenários.

Dê uma olhada nos cenários de uso suportados:

Cenário 1: Operação QUERY comando SELECT

Digamos que você tenha um banco de dados configurado e uma tabela com dados e que você queira invocar um DB V2 com uma query com o comando SELECT. Com isso, você terá acesso ao resultado da operação no pipeline através de um JSON.

Exemplo

1. Crie um pipeline e adicione um componente DB V2 2. Abra as configurações do componente 3. Selecione a operação QUERY 4. Escolha uma ACCOUNT para poder se autenticar no banco de dados 5. Defina um DATABASE URL (ex.: jdbc:mysql://myserver/mydb) 6. Defina um SQL STATEMENT (ex.: SELECT * FROM CLIENTES) 7. Clique em CONFIRMAR para salvar as configurações do componente 8. Conecte o trigger ao DB V2 9. Execute um teste no pipeline (você pode utilizar o comando CTRL + ENTER) 10. O resultado da query será apresentado:

{
  "data": [
    {
      "uf": "SP",
      "codigo": 1,
      "cidade": "Osasco",
      "logradouro": "Rua Laranjeiras",
      "name": "João Bosco",
      "due_date": "2019-03-27",
      "email": "joao.bosco@digibee.com.br",
      "cep": "XXXXX-XXX"
    },
    {
      "uf": "SP",
      "codigo": 2,
      "cidade": "São Paulo",
      "logradouro": "Rua Jõao Bosco",
      "name": "Roberto Carlos",
      "due_date": "2019-03-27",
      "email": "roberto.carlos@digibee.com.br",
      "cep": "XXXXX-XXX"
    }
  ],
  "updateCount": 0,
  "rowCount": 2
}

O resultado da query retorna um JSON com 3 propriedades em sua raiz: data, updateCount e rowCount.

  • data: vetor de objetos representando as linhas retornadas do banco de dados segundo a query definida. Cada elemento desse vetor contém propriedades que representam as colunas definidas na operação SELECT. Se a declaração fosse "SELECT name FROM CLIENTES", haveria apenas uma propriedade em cada um dos objetos no vetor data.

  • updateCount: indica quantas linhas da tabela foram afetadas pela query executada. Nesse exemplo o valor seria zero - já que a operação foi SELECT, nenhuma tabela foi afetada.

  • rowCount: indica quantas linhas foram retornadas pela query.

Cenário 2: Operação QUERY comando UPDATE

Digamos que você tenha um banco de dados configurado e uma tabela com dados e que você queira invocar um DB V2 com uma query com a operação UPDATE. Com isso, você terá acesso ao resultado desta operação no pipeline através de um JSON. Exemplo

1. Crie um pipeline e adicione um componente DB V2 2. Abra as configurações do componente 3. Selecione a operação QUERY 4. Escolha uma ACCOUNT para poder se autenticar no banco de dados 5. Defina um DATABASE URL (ex.: jdbc:mysql://myserver/mydb) 6. Defina um SQL STATEMENT (ex.: UPDATE CLIENTES SET uf='SP' WHERE uf is null) 7. Clique em CONFIRMAR para salvar as configurações do componente 8. Conecte o trigger ao DB V2 9. Execute um teste no pipeline (você pode utilizar o comando CTRL + ENTER) 10. O resultado da query será apresentado:

{  
    "data": null,  
    "updateCount": 5,  
    "rowCount": 0
}
  • updateCount: nesse exemplo, fica confirmada a alteração em 5 linhas da tabela.

Cenário 3: Operação QUERY comando DELETE

Digamos que você tenha um banco de dados configurado e uma tabela com dados e que você queira invocar um DB V2 com uma query com a operação DELETE. Com isso, você terá acesso ao resultado desta operação no pipeline através de um JSON.

Exemplo

1. Crie um pipeline e adicione um componente DB V2 2. Abra as configurações do componente 3. Selecione a operação QUERY 4. Escolha uma ACCOUNT para poder se autenticar no banco de dados 5. Defina um DATABASE URL (ex.: jdbc:mysql://myserver/mydb) 6. Defina um SQL STATEMENT (ex.: DELETE FROM CLIENTES WHERE codigo='111111') 7. Clique em CONFIRMAR para salvar as configurações do componente 8. Conecte o trigger ao DB V2 9. Execute um teste no pipeline (você pode utilizar o comando CTRL + ENTER) 10. O resultado da query será apresentado:

{  
    "data": null,  
    "updateCount": 1,  
    "rowCount": 0
}
  • updateCount: nesse exemplo, fica confirmado que 1 linha da tabela foi apagada.

Cenário 4: Operação QUERY comando INSERT

Digamos que você tenha um banco de dados configurado e uma tabela com dados e que você queira invocar um DB V2 com uma query com a operação INSERT. Com isso, você terá acesso ao resultado da operação no pipeline através de um JSON. Exemplo:

1. Crie um pipeline e adicione um componente DB V2

2. Abra as configurações do componente 3. Selecione a operação QUERY 4. Escolha uma ACCOUNT para poder se autenticar no banco de dados 5. Defina um DATABASE URL (ex.: jdbc:mysql://myserver/mydb 6. Defina um SQL STATEMENT (ex.: INSERT INTO CLIENTES (name, email) VALUES ('My Name', 'myname@email.com')) 7. Clique em CONFIRMAR para salvar as configurações do componente 8. Conecte o trigger ao DB V2 9. Execute um teste no pipeline (você pode utilizar o comando CTRL + ENTER) 10. O resultado da query será apresentado:

{  
    "data": null,  
    "updateCount": 1,  
    "rowCount": 0
}
  • updateCount: nesse exemplo, fica confirmado que 1 linha foi criada na tabela.

Cenário 5: Manter a conexão em drivers antigos ou com baixa confiabilidade

Digamos que você tenha um banco de dados incompatível com JDBC 4.0 ou que falhe em manter uma conexão confiável e que você queira invocar um DB V2 com uma query qualquer, mas 20 minutos depois fazer a mesma chamada. Com isso, a conexão com o banco de dados não é perdida.

A opção ADVANCED > CONNECTION TEST QUERY permite definir uma query que é executada antes da query definida no SQL STATEMENT para garantir que a conexão foi estabelecida com o banco e evitar falhas.

Essa opção vai permitir que uma nova conexão seja aberta, caso haja falha no teste de conexão. Isso evitará problemas de conexões "presas" e timeouts causados por queries anteriores que receberam erro.

IMPORTANTE: essa opção deve ser considerada apenas para bancos de dados mais antigos (com versão de suporte ao jdbc < 4.0).

1. Crie um pipeline e adicione um componente DB V2 2. Abra as configurações do componente 3. Selecione a operação QUERY 4. Escolha uma ACCOUNT para poder se autenticar no banco de dados 5. Defina um DATABASE URL (ex.: jdbc:mysql://myserver/mydb) 6. Defina um SQL STATEMENT (ex.: INSERT INTO CLIENTES (name, email) VALUES ('My Name', 'myname@email.com')) 7. Conecte o trigger ao DB V2 8. Selecione a opção ADVANCED (mais opções serão apresentadas) 9. Defina uma CONNECTION TEST QUERY (ex.: SELECT version()) 10. Clique em CONFIRMAR para salvar as configurações do componente 11. Execute um teste no pipeline (você pode utilizar o comando CTRL + ENTER) 12. O resultado da query será apresentado

Cenário 6: Interromper a execução do pipeline em caso de falha

Digamos que você tenha um banco de dados configurado e uma tabela com dados e que você queira invocar um DB V2 com uma QUERY ou PROCEDURE caso a operação falhe na interrupção da execução do pipeline.

A opção FAIL ON ERROR permite que o pipeline interrompa a sua execução em caso de falha na invocação do DB V2.

Cenário 7: Acessar e escrever arquivos no contexto de banco de dados

Digamos que você tenha um banco de dados configurado e uma tabela com dados do tipo BLOB e/ou CLOB e que você queira invocar um DB V2 com uma QUERY ou PROCEDURE. Com isso, você consegue tanto escrever arquivos disponíveis no pipeline quanto acessar arquivos valores de um campo BLOB e/ou CLOB do banco de dados.

As opções BLOB AS FILE e CLOB AS FILE permitem informar um caminho de arquivo para as operações com colunas do tipo BLOB e CLOB respectivamente - ou seja, invocar o comando INSERT e passar o caminho de um arquivo disponível no pipeline fará com que esse arquivo seja escrito no banco.

Caso o comando seja SELECT, o conteúdo do BLOB/CLOB se torna um arquivo dentro do pipeline.

Exemplo: passo 1 (ler arquivo)

1. Crie um pipeline e adicione um componente DB V2 2. Abra as configurações do componente 3. Defina o nome como 'Read-file' 4. Selecione a operação QUERY 5. Escolha uma ACCOUNT para poder se autenticar no banco de dados 6. Defina um DATABASE URL (ex.: jdbc:mysql://myserver/mydb) 7. Defina um SQL STATEMENT (ex.: SELECT blob FROM CLIENTES WHERE id=78) 8. Ative as opções BLOB AS FILE e/ou CLOB AS FILE (caso a opção CLOB AS FILE seja ativa, um novo campo CHARSET será exibido para que seja configurado o encoding do arquivo) 9. Clique em CONFIRMAR para salvar as configurações do componente 10. Conecte o trigger ao DB V2 (Read-file) 11. Execute um teste no pipeline (você pode utilizar o comando CTRL + ENTER) 12. O resultado da query será apresentado:

{
  "data": [
    {
      "blob": "E4G17F.file",
      "clob": "H2K89G.file"
    }
  ],
  "updateCount": 0,
  "rowCount": 1
}

Um arquivo chamado 'E4G17F.file' e outro chamado 'H2K89G.file' foram gerados e disponibilizados no pipeline.

Exemplo: passo 2 (escrever arquivo)

1. Adicione um componente DB V2 2. Abra as configurações do componente 3. Defina o nome como 'Write-file' 4. Selecione a operação QUERY 5. Escolha uma ACCOUNT para poder se autenticar no banco de dados 6. Defina um DATABASE URL (ex.: jdbc:mysql://myserver/mydb) 7. Defina um SQL STATEMENT (ex.: INSERT INTO CLIENTES (blob, clob) VALUES ( {{ message.data.blob }}, {{ message.data.clob }} ))

Note que expressões em Double Braces: {{ message.data.blob }} e {{ message.data.clob }} foram utilizadas.

Através delas é possível acessar o resultado do último componente. Nesse caso, data, que contém os resultados da query, foi acessada. Em seguida, blob e clob, que são os nomes dos arquivos gerados, foram acessados. Ou seja, está sendo passado o caminho para o arquivo 'E4G17F.file' e para o arquivo 'H2K89G.file' no comando INSERT para o campo blob e clob, respectivamente.

8. Ative a opção BLOB AS FILE e/ou CLOB AS FILE (caso a opção CLOB AS FILE seja ativa, um novo campo CHARSET será exibido para que seja configurado o encoding do arquivo)

9. No campo TYPE PROPERTIES clique no botão ADD

10. Uma seção será apresentada para que você defina os campos:

  • Key como 0 (cada Double Braces possui um índice, sendo que esse se refere ao primeiro)

  • TYPE como BLOB

  • OUT PARAMETER NAME em branco

  • PARAMETER TYPE como in

  • Key como 1 (cada Double Braces possui um índice, sendo que esse se refere ao segundo)

  • TYPE como CLOB

  • OUT PARAMETER NAME em branco

  • PARAMETER TYPE como in

11. Clique em CONFIRMAR para salvar as configurações do componente 12. Conecte o DB V2 (Read-file) ao DB V2 (Write-file) 13. Execute um teste no pipeline (você pode utilizar o comando CTRL + ENTER) 14. O resultado da query será apresentado:

{  
    "data": null,  
    "updateCount": 1,  
    "rowCount": 0
}

O resultado indica que uma linha da tabela foi afetada. Nesse caso, o primeiro componente (Read-file) leu os conteúdos blob e clob do banco de dados e criou dois arquivos. Em seguida, o componente (Write-file) pegou esses arquivos disponíveis no pipeline e os inseriu no banco de dados em um novo registro.

Cenário 8: Executar uma procedure

Digamos que você tenha um banco de dados configurado com uma procedure existente e que você queira invocar um DB V2 em modo PROCEDURE. Com isso, você consegue executar uma procedure existente e obter o resultado da operação no pipeline através de um JSON.

Exemplo

A seguinte procedure deve existir no banco de dados para esse exemplo:

CREATE 
PROCEDURE `proc_sum_one`(INOUT `num` INTEGER)
BEGIN   
    SET `num` = `num` + 1;
END

1. Crie um pipeline e adicione um componente DB V2 2. Abra as configurações do componente 3. Selecione a operação PROCEDURE 4. Escolha uma ACCOUNT para poder se autenticar no banco de dados 5. Defina um DATABASE URL (ex.: jdbc:mysql://myserver/mydb) 6. Defina um SQL STATEMENT ( ex.: call proc_sum_one({{ message.num }}) )

Note que usamos a expressão em Double Braces: {{ message.num }} Através dela é possível acessar o resultado do último componente. 7. No campo TYPE PROPERTIES clique no botão ADD 8. Uma seção será apresentada conforme a imagem acima para que você defina os campos:

  • Key como 0 (cada Double Braces possui um índice, sendo que esse se refere ao primeiro)

  • TYPE como INTEGER

  • OUT PARAMETER NAME como result (define o parâmetro resultante da procedure)

  • PARAMETER TYPE como INOUT

9. Clique em CONFIRMAR para salvar as configurações do componente 10. Conecte o trigger ao DB V2 11. Abra o Painel de execução e passe um valor de entrada (ex.: { "num": 3 }) 12. Execute um teste no pipeline (você pode utilizar o comando CTRL + ENTER) 13. O resultado da query será apresentado:

{  
    "data": {    
        "result": 4  
    },  
    "success": true
}

Cenário 9: Definir propriedades personalizadas de conexão

Digamos que você tenha um banco de dados configurado e que você queira invocar um DB V2. Com isso, você consegue especificar propriedades personalizadas de conexão.

Exemplo

1. Abra as configurações do componente 2. Selecione a operação QUERY 3. Escolha uma ACCOUNT para poder se autenticar no banco de dados 4. Defina um DATABASE URL (ex.: jdbc:mysql://myserver/mydb) 5. Defina um SQL STATEMENT (e.g.) SELECT * FROM CLIENTES) 6. Defina o campo CUSTOM CONNECTION PROPERTIES (ex.: { "connectTimeout": 1 }) 7. Clique em CONFIRMAR para salvar as configurações do componente 8. Conecte o trigger ao DB V2 9. Execute um teste no pipeline (você pode utilizar o comando CTRL + ENTER) 10. O resultado da query será apresentado:

{  
    "success": false,  
    "message": "Could not establish connection to the database",  
    "error": "java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=xxxxx)(port=XXX)(type=master) : null"
}

Nesse caso, a propriedade específica de conexão connectTimeout foi definida como 1 (um segundo) para demonstrar que ela foi considerada e gerou um erro de conexão.

Cenário 10: Manter conexão ativa por 5 ou 30 minutos

Digamos que você tenha um banco de dados configurado e que você queira invocar um DB V2. Com isso, você pode optar por manter a conexão com o banco ativa por 5 ou 30 minutos.

A opção KEEP CONNECTION te permite estender o tempo padrão de 5 minutos para 30 minutos de conexão ativa com o banco de dados.

Cenário 11: Ler tipos de dados customizados de um banco de dados Oracle

Digamos que você tenha um banco de dados Oracle configurado com uma tabela que contenha dados de um tipo customizado e que você queira invocar um DB V2 para consultar esses dados.

Exemplo

Você tem a tabela criada com a seguinte estrutura:

CREATE TABLE projeto (
    nome VARCHAR2(50),
    coordenador OWNER
);

E o tipo customizado OWNER criado da seguinte maneira:

CREATE TYPE OWNER AS OBJECT

(
    nome VARCHAR2(50), 
    email VARCHAR2(30) 
);

Ao executar query abaixo:

SELECT * FROM projeto

Você tem o resultado:

{
    "data": [
        {
            "nome": "Projeto Exemplo",
            "owner": [
                "Nome Coordenador",
                "Email Coordenador"
            ]
        }
    ],
    "updateCount": 0,
    "rowCount": 1
}

Se o tipo customizado utilizar outros tipos customizado na sua estrutura, você teria o resultado com os dados aninhados da seguinte maneira:

{
    "data": [
        {
            "nome": "Projeto Exemplo",
            "owner": [
                "Nome Coordenador",
                "Email Coordenador",
                [
                    "Campo de um 2º tipo customizado",
                    [
                        "Campo de um 3º tipo customizado"
                    ]
                ]
            ]
        }
    ],
    "updateCount": 0,
    "rowCount": 1
}

IMPORTANTE: consultas de dados customizados não expõem os nomes dos campos informados dentro do tipo customizado, apenas a ordem dos campos.

No exemplo acima, o primeiro elemento do array "owner" corresponde ao campo "nome" e o segundo elemento ao campo "email", ambos definidos nessa respectiva ordem dentro do tipo OWNER.Para consultas via PROCEDURE, o parâmetro OUT PARAMETER NAME em TYPE PROPERTIES deve receber obrigatoriamente o nome do tipo customizado que, no exemplo acima, seria o valor OWNER.

Cenário 12: Enviar tipos de dados customizados para um banco de dados Oracle

Digamos que você tenha um banco de dados Oracle configurado com uma tabela que contenha dados de um tipo customizado (Struct) e que você queira invocar um DB V2 para inserir dados nessa tabela.

IMPORTANTE: o componente DB V2 não suporta Doubles Braces para resolver dados customizados (Struct) utilizando comandos INSERT e UPDATE.

Exemplo

Você tem os tipos customizados e a tabela criados com as seguintes estruturas:

  • CREATE OR REPLACE TYPE CONTACT AS OBJECT

(
    NAME  VARCHAR2(50),  
    PHONE VARCHAR2(15)
);

  • CREATE OR REPLACE TYPE PERSON AS OBJECT

(
  ID           NUMBER(10,0),
  NAME         VARCHAR2(50),
  CONTACT_INFO CONTACT
);

  • CREATE OR REPLACE TYPE DEPARTMENT AS OBJECT

(
  ID      NUMBER(10,0),
  NAME    VARCHAR2(50)
);

  • CREATE TABLE EMPLOYEE

(
  PERSON PERSON, 		
  DEPT   DEPARTMENT,
  SALARY NUMBER(12,2)
);

Para que esses dados sejam inseridos na tabela, é possível utilizar as seguintes estruturas:

Dados a serem inseridos:

  {
  	"personName": "John A.",
  	"contactName": "John",
  	"contactPhone": "99999",
  	"departmentName": "IT"
  }

  • Através de INSERT a partir do resultado de uma QUERY

INSERT INTO EMPLOYEE
SELECT PERSON(DBMS_RANDOM.VALUE(0,999999), {{ message.personName }}, CONTACT({{ message.contactName }}, {{ message.contactPhone }})),
	   DEPARTMENT(DBMS_RANDOM.VALUE(0,999999), {{ UPPERCASE(message.departmentName) }}),
	   3030.67 SALARY
  FROM DUAL

  • Através de PROCEDURE:PROCEDURE previamente criada na base de dados

CREATE OR REPLACE PROCEDURE MY_PROC(DEPT IN DEPARTMENT, EMP IN OUT PERSON) IS
  BEGIN
	 SAL  := 4567.89 * 1.10;
	 INSERT INTO EMPLOYEE VALUES (EMP, DEPT, SAL);	 
  EXCEPTION
  	WHEN OTHERS THEN
  		RAISE_APPLICATION_ERROR(-20001,'An error was encountered - '||SQLCODE||' - ERROR: '||SQLERRM);
  END;

  • Chamada da PROCEDURE

DECLARE
  	CONT CONTACT;
    DEPT DEPARTMENT;
    SAL  EMPLOYEE.SALARY%TYPE;
BEGIN
    DEPT := DEPARTMENT(TRUNC(DBMS_RANDOM.VALUE(0,999999)), {{ UPPERCASE(message.departmentName) }});
    CONT := CONTACT({{ message.contactName }}, {{ message.contactPhone }});
    EMP  := PERSON(TRUNC(DBMS_RANDOM.VALUE(0,999999)), {{ message.personName }}, CONT);
	  MY_PROC(EMP);
END;

  • Através de Script SQL

DECLARE
  	EMP  PERSON;
    CONT CONTACT;
  	DEPT DEPARTMENT;
    SAL  EMPLOYEE.SALARY%TYPE;
  BEGIN
	 DEPT := DEPARTMENT(TRUNC(DBMS_RANDOM.VALUE(0,999999)), {{ UPPERCASE(message.personName) }});
	 CONT := CONTACT({{ message.contactName }}, {{ message.contactPhone }});
	 EMP  := PERSON(TRUNC(DBMS_RANDOM.VALUE(0,999999)), {{ message.personName }}, CONT);
	 SAL  := 4567.89;
	 INSERT INTO EMPLOYEE VALUES (EMP, DEPT, SAL);	 
  EXCEPTION
  	WHEN OTHERS THEN
  		RAISE_APPLICATION_ERROR(-20001,'An error was encountered - '||SQLCODE||' - ERROR: '||SQLERRM);

  END;

Cenário 13 - Operação QUERY comando SELECT - Raw SQL

Digamos que você tenha um fluxo de integração que precise realizar duas queries diferentes em uma base de dados, dependendo de algumas regras de negócio:

QUERY 1:

SELECT * FROM TABLE_1
WHERE ID = 123

QUERY 2:

SELECT * FROM TABLE_2
WHERE CODE = 'ABC'

O DB V2 conta com a funcionalidade Raw SQL Statement que permite que você referencie uma query completa através de uma declaração Double Braces, portanto a mesma referência pode ser aplicada a valores diferentes.

Para usar essa funcionalidade, as queries devem ser previamente configuradas por outro componente como o Template Transformer, e então referenciadas no DB V2.

Exemplo

1. Crie um pipeline e adicione o Template Transformer e o DB V2;

2. Abra as configurações do componente Template Transformer;

3. Ative a opção Preserve Original;

4. Defina o body:

SELECT * FROM 
${table}
WHERE 
<#if id?? > 
    ID = {{ message._query.id }} 
</#if>

<#if code??>
    CODE = {{ message._query.code }} 
</#if>

5. Clique em Confirm para salvar as configurações do componente;

6. Abra as configurações do componente DB V2;

7. Selecione a operação Query;

8. Escolha uma account para permitir a autenticação na base de dados;

9. Defina a Database URL (ex.:jdbc:mysql://myserver/mydb);

10. Defina o SQL Statement como {{ message.query }};

11. Ative a opção Advanced;

12. Ative a opção Raw SQL Statement;

13. Clique em Confirm para salvar as configurações do componente;

14. Conecte o Template Transformer ao DB V2;

15. Conecte o trigger ao Template Transformer;

16. Execute um teste no pipeline passando um payload de entrada:

Payload para QUERY 1:

{
    "query": {
        "table": "TABLE_1",
        "id": 123
    }
}

Payload para QUERY 2:

{
    "query": {
        "table": "TABLE_2",
        "code": "ABC"
    }
}>

17. O resultado é exibido com base na query executada, como mostrado na sequência:

Resultado para QUERY 1:

{
    "query": {
        "table": "TABLE_1",
        "id": 123
    }
}

Resultado para QUERY 2:

{
    "query": {
        "table": "TABLE_2",
        "code": "ABC"
    }
}>

O resultado da query retorna um JSON com 3 propriedades em sua raiz: data, updateCount e rowCount.

  • data: objeto array representando as linhas retornadas da base de dados, de acordo com a query executada. Cada elemento deste array tem propriedades que representam as colunas definidas na operação Select. Caso a declaração seja "SELECT name FROM TABLE_1 WHERE ID = 123" ou "SELECT fullName FROM TABLE_2 WHERE CODE = 'ABC'", haveria apenas uma propriedade em cada um dos objetos no array de dados.

  • updateCount: indica quantas linhas da tabela foram afetadas pela query executada. No exemplo acima, o valor seria zero; uma vez que a operação escolhida foi Select, nenhuma tabela foi afetada.

  • rowCount: indica quantas linhas foram retornadas pela query.

IMPORTANTE: a query a ser referenciada através de Double Braces no DB V2 pode ser configurada previamente por outros componentes como JSON Generator ou Transformer (JOLT). Porém, ao usar o Template Transformer você pode combiná-la com a tecnologia FreeMarker para validar os dados antes de executar a target query e também aplicar mecanismos para prevenir ataques SQL injection no pipeline. A declaração Double Braces não é resolvida pelo Template Transformer mas pelo DB V2, que por padrão configura e valida os parâmetros da instrução SQL previamente (PreparedStatement). Isso significa que usar o Template Transformer em conjunto com o DB V2 é uma forma mais segura e simples de criar queries comparado a outros componentes.

Last updated