<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[André Martins]]></title><description><![CDATA[Desenvolvedor de Software Backend]]></description><link>https://andresilva.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 18 Apr 2026 10:35:27 GMT</lastBuildDate><atom:link href="https://andresilva.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Handler Map]]></title><description><![CDATA[Imagine que você está em um cenário onde tem várias funções que precisam ser executadas conforme um caminho seja passado por parâmetro, por exemplo: dentro de um domínio de clientes, precisamos executar funções a partir de uma chamada desse path, e, ...]]></description><link>https://andresilva.dev/handler-map</link><guid isPermaLink="true">https://andresilva.dev/handler-map</guid><category><![CDATA[patterns]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[André Martins]]></dc:creator><pubDate>Thu, 21 Aug 2025 02:38:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1755743868340/e4256cfa-17a9-4542-9ef7-1f8f66ae9f5a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Imagine que você está em um cenário onde tem várias funções que precisam ser executadas conforme um caminho seja passado por parâmetro, por exemplo: dentro de um domínio de clientes, precisamos executar funções a partir de uma chamada desse path, e, nesse caso, temos sabedoria para não resolver isso com switch case ou da forma abaixo.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> Cliente {
  <span class="hljs-keyword">public</span> <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> _id: <span class="hljs-built_in">number</span>, <span class="hljs-keyword">private</span> _name: <span class="hljs-built_in">string</span></span>) {}

  get clientes(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._id;
  }

  <span class="hljs-comment">// outros comportamentos do cliente</span>
}

<span class="hljs-keyword">class</span> ClienteService {
  <span class="hljs-keyword">public</span> execute(path: <span class="hljs-built_in">string</span>) {
    <span class="hljs-keyword">if</span> (path === <span class="hljs-string">"sincronizarImagens"</span>) {
      <span class="hljs-comment">// lógica para sincronizar as imagens do cliente</span>
    }

    <span class="hljs-keyword">if</span> (path === <span class="hljs-string">"sincronizarReport"</span>) {
      <span class="hljs-comment">// lógica para sincronizar os relatórios do cliente</span>
    }

    <span class="hljs-keyword">if</span> (path === <span class="hljs-string">"sincronizarLogs"</span>) {
      <span class="hljs-comment">// lógica para sincronizar os logs do cliente</span>
    }
  }
}
</code></pre>
<h2 id="heading-iniciando-solucao">Iniciando solução</h2>
<p>Podemos pensar em excluir essa lógica de ifs, e uma forma de fazer isso é com o Handler Map.</p>
<p>A primeira parte é definir um tipo onde teremos uma chave e o tipo de parâmetros da função de <code>callback</code>. Perceba que, nesse ponto, podemos usar qualquer <code>string</code> como tipo da chave, e nos parâmetros estamos esperando o <em>ID</em> e não vamos retornar nada.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">type</span> HandlerMap = {
  [key: <span class="hljs-built_in">string</span>]: <span class="hljs-function">(<span class="hljs-params">id: <span class="hljs-built_in">number</span></span>) =&gt;</span> <span class="hljs-built_in">void</span>;
};
</code></pre>
<p>Agora precisamos de uma função para resolver nossa callback conforme o parâmetro que passarmos, mas o detalhe é que não vamos passar parâmetro nenhum, te mostro já.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> ClientService {
    <span class="hljs-keyword">private</span> resolverHandlerMapByName(): HandlerMap {
        <span class="hljs-keyword">return</span> {
            sincronizarImagens:<span class="hljs-function">(<span class="hljs-params">id: <span class="hljs-built_in">number</span></span>) =&gt;</span> <span class="hljs-built_in">this</span>.searchImages(id),
            sincronizarReport(id: <span class="hljs-built_in">number</span>) =&gt; <span class="hljs-built_in">this</span>.sincronizarReport(id),
            sincronizarLogs(id: <span class="hljs-built_in">number</span>) =&gt; <span class="hljs-built_in">this</span>.sincronizarLogs(id),
        }
    }

    sincronizarImagens(id: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">void</span> {
        <span class="hljs-comment">// lógica para sincronizar as imagens do cliente</span>
    }

    sincronizarReport(id: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">void</span> {
        <span class="hljs-comment">// lógica para sincronizar os relatórios do cliente</span>
    }

    sincronizarLogs(id: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">void</span> {
        <span class="hljs-comment">// lógica para sincronizar os logs do cliente</span>
    }
}
</code></pre>
<p>Conforme o exemplo acima, resolvemos nossa execução de forma transparente, sem a necessidade de verificações estranhas.</p>
<h2 id="heading-como-usar">Como usar?</h2>
<pre><code class="lang-typescript"><span class="hljs-keyword">class</span> ClientService {

    execute(path: <span class="hljs-built_in">string</span>) {

        <span class="hljs-keyword">const</span> id = <span class="hljs-number">123</span>;

        <span class="hljs-keyword">const</span> handler = <span class="hljs-built_in">this</span>.resolverHandlerMapByName()[path]

        handler(id);

    }

    <span class="hljs-keyword">private</span> resolverHandlerMapByName(): HandlerMap {
        <span class="hljs-keyword">return</span> {
            sincronizarImagens:<span class="hljs-function">(<span class="hljs-params">id: <span class="hljs-built_in">number</span></span>) =&gt;</span> <span class="hljs-built_in">this</span>.searchImages(id),
            sincronizarReport(id: <span class="hljs-built_in">number</span>) =&gt; <span class="hljs-built_in">this</span>.sincronizarReport(id),
            sincronizarLogs(id: <span class="hljs-built_in">number</span>) =&gt; <span class="hljs-built_in">this</span>.sincronizarLogs(id),
        }
    }

    sincronizarImagens(id: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">void</span> {
        <span class="hljs-comment">// lógica para sincronizar as imagens do cliente</span>
    }

    sincronizarReport(id: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">void</span> {
        <span class="hljs-comment">// lógica para sincronizar os relatórios do cliente</span>
    }

    sincronizarLogs(id: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">void</span> {
        <span class="hljs-comment">// lógica para sincronizar os logs do cliente</span>
    }
}
</code></pre>
<p>Dessa forma conseguimos resolver nossa chamada com HandlerMap de forma transparente, há outras formas de resolver isso também, mas essa é uma forma que deixa as coisas bem legíveis.</p>
]]></content:encoded></item><item><title><![CDATA[Vetor não ordenado]]></title><description><![CDATA[Vetores não ordenados são estruturas de dados para armazenar dados em sequência. Se imaginarmos uma variável em um programa, ela é composta por um dado anexado a um endereço de memória. Quando se trata de um vetor, estamos falando de conjuntos de dad...]]></description><link>https://andresilva.dev/vetor-nao-ordenado</link><guid isPermaLink="true">https://andresilva.dev/vetor-nao-ordenado</guid><category><![CDATA[DSA]]></category><category><![CDATA[algoritmos-e-estrutura-de-dados]]></category><category><![CDATA[Python]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[André Martins]]></dc:creator><pubDate>Thu, 21 Aug 2025 02:20:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/gC_aoAjQl2Q/upload/6ce1b15c0686f0202eb7509ab9809902.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Vetores não ordenados são estruturas de dados para armazenar dados em sequência. Se imaginarmos uma variável em um programa, ela é composta por um dado anexado a um endereço de memória. Quando se trata de um vetor, estamos falando de conjuntos de dados.</p>
<h2 id="heading-qual-a-utilidade-de-um-vetor-nao-ordenado">Qual a utilidade de um vetor não ordenado?</h2>
<p>Um vetor não ordenado tem a utilidade de guardar agrupamentos de dados que, como o nome já diz, não necessitam estritamente de uma ordem. Vetores sempre terão um limite, e esse é o diferencial para uma lista. Em um vetor não ordenado, pode-se guardar um grupo de objetos ou primitivos temporários. Vetores não ordenados são uma boa escolha na hora de lidar com poucos dados fixos.</p>
<h2 id="heading-implementacao-em-python">Implementação em Python</h2>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-string">'''
Vetor não ordenado de inteiros, não permite inserção de valores duplicados
Operações:
    inserir
    imprimir
    excluir
    pesquisar
'''</span>


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VetorNaoOrdenado</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, capacidade_vetor</span>):</span>
        self.capacidade_vetor = capacidade_vetor
        self.ultima_posicao = <span class="hljs-number">-1</span>
        self.valores = np.empty(self.capacidade_vetor, dtype=int)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">insere_no_vetor</span>(<span class="hljs-params">self, valor</span>):</span>
        self.ultima_posicao += <span class="hljs-number">1</span>
        self.valores[self.ultima_posicao] = valor

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">insere</span>(<span class="hljs-params">self, valor</span>):</span>
        <span class="hljs-keyword">if</span> self.ultima_posicao == self.capacidade_vetor - <span class="hljs-number">1</span>:
            print(<span class="hljs-string">'A capacidade foi atingida'</span>)
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">if</span> self.ultima_posicao == <span class="hljs-number">-1</span>:
                self.insere_no_vetor(valor)
            <span class="hljs-keyword">else</span>:
                <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(self.ultima_posicao + <span class="hljs-number">1</span>):
                    <span class="hljs-keyword">if</span> self.valores[i] == valor:
                        print(<span class="hljs-string">f'Não é permitido inserir <span class="hljs-subst">{valor}</span> já existe no vetor'</span>)
                        <span class="hljs-keyword">return</span>
                self.insere_no_vetor(valor)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">pesquisa_linear</span>(<span class="hljs-params">self, valor</span>):</span>
        <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(self.ultima_posicao + <span class="hljs-number">1</span>):
            <span class="hljs-keyword">if</span> self.valores[i] == valor:
                <span class="hljs-keyword">return</span> i
        <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">excluir</span>(<span class="hljs-params">self, valor</span>):</span>
        <span class="hljs-keyword">if</span> self.ultima_posicao == <span class="hljs-number">-1</span>:
            <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>
        indice_pesquisado = self.pesquisa_linear(valor)
        <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(indice_pesquisado, self.ultima_posicao):
            self.valores[i] = self.valores[i + <span class="hljs-number">1</span>]
        self.ultima_posicao -= <span class="hljs-number">1</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">imprime_valores</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">if</span> self.ultima_posicao == <span class="hljs-number">-1</span>:
            print(<span class="hljs-string">'O vetor está vazio'</span>)
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(self.ultima_posicao + <span class="hljs-number">1</span>):
                print(i, <span class="hljs-string">'--&gt;'</span>, <span class="hljs-string">'['</span>, self.valores[i], <span class="hljs-string">']'</span>)


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
    vetor = VetorNaoOrdenado(<span class="hljs-number">5</span>)
    vetor.insere(<span class="hljs-number">1</span>)
    vetor.insere(<span class="hljs-number">8</span>)
    vetor.insere(<span class="hljs-number">7</span>)
    vetor.insere(<span class="hljs-number">6</span>)
    vetor.insere(<span class="hljs-number">5</span>)
    vetor.excluir(<span class="hljs-number">7</span>)
    vetor.imprime_valores()

    print(<span class="hljs-string">'Posicao'</span>, vetor.pesquisa_linear(<span class="hljs-number">19</span>))
</code></pre>
<h2 id="heading-implementacao-em-typescript">Implementação em Typescript</h2>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> VetorNaoOrdenado {
  <span class="hljs-keyword">private</span> ultimaPosicao: <span class="hljs-built_in">number</span>;
  <span class="hljs-keyword">private</span> vetor: <span class="hljs-built_in">number</span>[];

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> capacidade: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.ultimaPosicao = <span class="hljs-number">-1</span>;
    <span class="hljs-built_in">this</span>.vetor = [];
  }

  valorNaoEncontrado(value: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.procurar(value) === <span class="hljs-number">-1</span>;
  }

  inserir(value: <span class="hljs-built_in">number</span>) {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.ultimaPosicao == <span class="hljs-built_in">this</span>.capacidade - <span class="hljs-number">1</span>) {
      <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.valorNaoEncontrado(value)) {
      <span class="hljs-built_in">this</span>.ultimaPosicao += <span class="hljs-number">1</span>;
      <span class="hljs-built_in">this</span>.vetor[<span class="hljs-built_in">this</span>.ultimaPosicao] = value;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }
  }

  remover(value: <span class="hljs-built_in">number</span>) {
    <span class="hljs-keyword">const</span> foundIndex = <span class="hljs-built_in">this</span>.procurar(value);
    <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.vetor[foundIndex]) {
      <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
    }

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-built_in">this</span>.capacidade - <span class="hljs-number">1</span>; i++) {
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.vetor[i] == value) {
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i; j &lt; <span class="hljs-built_in">this</span>.capacidade - <span class="hljs-number">1</span>; j++) {
          <span class="hljs-built_in">this</span>.vetor[j] = <span class="hljs-built_in">this</span>.vetor[j + <span class="hljs-number">1</span>];
        }
      }
    }
    <span class="hljs-built_in">this</span>.ultimaPosicao -= <span class="hljs-number">1</span>;
  }

  procurar(value: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">let</span> result = <span class="hljs-number">-1</span>;
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-built_in">this</span>.capacidade - <span class="hljs-number">1</span>; i++) {
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.vetor[i] === value) {
        result = i;
      }
    }
    <span class="hljs-keyword">return</span> result;
  }

  imprimir() {
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-built_in">this</span>.capacidade - <span class="hljs-number">1</span>; i++) {
      <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.vetor[i]) <span class="hljs-keyword">continue</span>;
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`[Posição: <span class="hljs-subst">${i}</span>] -&gt; Valor: <span class="hljs-subst">${<span class="hljs-built_in">this</span>.vetor[i]}</span>`</span>);
    }
  }
}

<span class="hljs-keyword">const</span> lista = <span class="hljs-keyword">new</span> VetorNaoOrdenado(<span class="hljs-number">5</span>);

lista.inserir(<span class="hljs-number">1</span>);
lista.inserir(<span class="hljs-number">3</span>);
lista.inserir(<span class="hljs-number">2</span>);
lista.inserir(<span class="hljs-number">10</span>);

lista.remover(<span class="hljs-number">1</span>);

lista.imprimir();
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Iniciando leitura de logs do MySQL com Debezium [Parte-1]]]></title><description><![CDATA[Muitas vezes, estamos lidando com um legado e, de alguma forma, precisamos escutar ou saber das operações que estão ocorrendo em determinadas tabelas, mas nem sempre e acredito que não seja indicado connectar uma nova aplicação em sua legacy database...]]></description><link>https://andresilva.dev/iniciando-leitura-de-logs-do-mysql-com-debezium-parte-1</link><guid isPermaLink="true">https://andresilva.dev/iniciando-leitura-de-logs-do-mysql-com-debezium-parte-1</guid><category><![CDATA[kafka]]></category><category><![CDATA[debezium]]></category><category><![CDATA[MySQL]]></category><category><![CDATA[Streams]]></category><dc:creator><![CDATA[André Martins]]></dc:creator><pubDate>Thu, 21 Aug 2025 02:09:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/LCesurcI3PM/upload/1502726d43b386a91abc8aec9e513038.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Muitas vezes, estamos lidando com um legado e, de alguma forma, precisamos escutar ou saber das operações que estão ocorrendo em determinadas tabelas, mas nem sempre e acredito que não seja indicado connectar uma nova aplicação em sua legacy database. Uma forma de fazer este trabalho é usar o bom e velhor Debezium, que irá ler os logs das tabelas que ocorrerem em seu banco de dados, claro, apenas nas tabelas listadas em sua configuração.</p>
<h1 id="heading-como-subir-o-kafka-com-debezium-localmente">Como subir o Kafka com Debezium localmente?</h1>
<pre><code class="lang-yaml"><span class="hljs-attr">services:</span>
  <span class="hljs-attr">mysql-kafka:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">mysql:5.7</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">MYSQL_DATABASE=kafka-test</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">MYSQL_ROOT_PASSWORD=root</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-number">3306</span><span class="hljs-string">:3306</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">.data/mysql:/var/lib/mysql</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">kafka-test-network</span>

  <span class="hljs-attr">connect:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">debezium/connect:latest</span>
    <span class="hljs-attr">depends_on:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">kafka</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">mysql-kafka</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">BOOTSTRAP_SERVERS=kafka:9092</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">GROUP_ID=1</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">CONFIG_STORAGE_TOPIC=my_connect_configs</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">OFFSET_STORAGE_TOPIC=my_connect_offsets</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">STATUS_STORAGE_TOPIC=my_connect_statuses</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-number">8083</span><span class="hljs-string">:8083</span>
      <span class="hljs-bullet">-</span> <span class="hljs-number">5005</span><span class="hljs-string">:5005</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">kafka-test-network</span>

  <span class="hljs-attr">zookeeper:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">confluentinc/cp-zookeeper:latest</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-attr">ZOOKEEPER_CLIENT_PORT:</span> <span class="hljs-number">2181</span>
      <span class="hljs-attr">ZOOKEEPER_TICK_TIME:</span> <span class="hljs-number">2000</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">kafka-test-network</span>
    <span class="hljs-attr">deploy:</span>
      <span class="hljs-attr">resources:</span>
        <span class="hljs-attr">limits:</span>
          <span class="hljs-attr">cpus:</span> <span class="hljs-string">"0.8"</span>
          <span class="hljs-attr">memory:</span> <span class="hljs-string">800M</span>
        <span class="hljs-attr">reservations:</span>
          <span class="hljs-attr">memory:</span> <span class="hljs-string">100M</span>

  <span class="hljs-attr">kafka:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">confluentinc/cp-kafka:latest</span>
    <span class="hljs-attr">depends_on:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">zookeeper</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"9092:9092"</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"9094:9094"</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-attr">KAFKA_BROKER_ID:</span> <span class="hljs-number">1</span>
      <span class="hljs-attr">KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR:</span> <span class="hljs-number">1</span>
      <span class="hljs-attr">KAFKA_NUM_PARTITIONS:</span> <span class="hljs-number">1</span>
      <span class="hljs-attr">KAFKA_DEFAULT_REPLICATION_FACTOR:</span> <span class="hljs-number">1</span>
      <span class="hljs-attr">KAFKA_AUTO_CREATE_TOPICS_ENABLE:</span> <span class="hljs-string">"true"</span>
      <span class="hljs-attr">KAFKA_ZOOKEEPER_CONNECT:</span> <span class="hljs-string">zookeeper:2181</span>
      <span class="hljs-attr">KAFKA_INTER_BROKER_LISTENER_NAME:</span> <span class="hljs-string">INTERNAL</span>
      <span class="hljs-attr">KAFKA_LISTENERS:</span> <span class="hljs-string">INTERNAL://:9092,OUTSIDE://:9094</span>
      <span class="hljs-attr">KAFKA_ADVERTISED_LISTENERS:</span> <span class="hljs-string">INTERNAL://kafka:9092,OUTSIDE://localhost:9094</span>
      <span class="hljs-attr">KAFKA_LISTENER_SECURITY_PROTOCOL_MAP:</span> <span class="hljs-string">INTERNAL:PLAINTEXT,OUTSIDE:PLAINTEXT</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">kafka-test-network</span>
    <span class="hljs-attr">deploy:</span>
      <span class="hljs-attr">resources:</span>
        <span class="hljs-attr">limits:</span>
          <span class="hljs-attr">cpus:</span> <span class="hljs-string">"0.8"</span>
          <span class="hljs-attr">memory:</span> <span class="hljs-string">800M</span>
        <span class="hljs-attr">reservations:</span>
          <span class="hljs-attr">memory:</span> <span class="hljs-string">100M</span>

<span class="hljs-attr">networks:</span>
  <span class="hljs-attr">kafka-test-network:</span>
    <span class="hljs-attr">driver:</span> <span class="hljs-string">bridge</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">kafka-test-network</span>
</code></pre>
<p>A primeira imagem que precisamos é do próprio MySQL. Nele, vamos criar um banco para posteriormente listar os logs.</p>
<p>Em seguida, iniciamos a imagem do Debezium e adicionamos as dependências do Kafka e do Zookeeper.</p>
<p><strong>Obs.:</strong> Este docker-compose é apenas um exemplo. O recomendado é usar um arquivo .env para adicionar os parâmetros e configurações de nossas imagens.</p>
<h2 id="heading-rodando-o-projeto">Rodando o projeto</h2>
<pre><code class="lang-bash">$ docker compose up
</code></pre>
<p>A partir desse momento, se tudo der certo, teremos toda a nossa infraestrutura rodando localmente para testarmos.</p>
<p>Para ver o estado dos containers ativos, você pode executar:</p>
<pre><code class="lang-bash">docker ps
</code></pre>
<p>Se tudo ocorreu bem, vamos ver uma saída dos containers ativos</p>
<h2 id="heading-montando-script-sql">Montando script SQL</h2>
<p>Vamos criar uma tabela no banco para posteriormente inserirmos dados e ler como tópicos de criação no Debezium.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">use</span> <span class="hljs-string">`kafka-test`</span>;
<span class="hljs-keyword">drop</span> <span class="hljs-keyword">table</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">exists</span> <span class="hljs-keyword">users</span>;
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">table</span> <span class="hljs-keyword">users</span>(
    <span class="hljs-keyword">id</span> <span class="hljs-built_in">int</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span> auto_increment,
    <span class="hljs-keyword">name</span> <span class="hljs-built_in">varchar</span>(<span class="hljs-number">50</span>) <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span>,
    age <span class="hljs-built_in">int</span> <span class="hljs-keyword">default</span> <span class="hljs-literal">null</span>,
    surname <span class="hljs-built_in">varchar</span>(<span class="hljs-number">40</span>) <span class="hljs-keyword">default</span> <span class="hljs-literal">null</span>,
    primary <span class="hljs-keyword">key</span> (<span class="hljs-keyword">id</span>)
);
</code></pre>
<h2 id="heading-definindo-primeiro-connector">Definindo primeiro connector</h2>
<p>O Debezium possui sua própria API REST e diversos plugins. O que vamos precisar para ele começar a ler as alterações dessa tabela é:</p>
<pre><code class="lang-bash">curl --location <span class="hljs-string">'localhost:8083/connectors'</span> \
--header <span class="hljs-string">'Content-Type: application/json'</span> \
--data <span class="hljs-string">'{
    "name": "database-connector",
    "config": {
        "connector.class": "io.debezium.connector.mysql.MySqlConnector",
        "tasks.max": "1",
        "database.hostname": "mysql-kafka",
        "database.port": "3306",
        "database.user": "root",
        "database.password": "root",
        "database.server.id": "184054",
        "topic.prefix": "connector",
        "database.include.list": "kafka-test.users",
        "schema.history.internal.kafka.bootstrap.servers": "kafka:9092",
        "schema.history.internal.kafka.topic": "schema-changes.inventory"
    }
}'</span>
</code></pre>
<p>Nesse ponto perceba que adicionamos como <code>connector</code> o prefixo de nossos tópicos gerados pelo debezium, outro ponto é que apontamos todas as configurações de conexão com banco e kafka diretamente pela rede interna que criamos no nosso docker-compose.</p>
<h2 id="heading-inserindo-dados">Inserindo dados</h2>
<p>Agora que temos nosso plugin ativo, podemos adicionar dados no banco. Esses dados vão produzir tópicos que vamos poder consumir e posteriormente gerar eventos ou mesmo trabalhar com streams.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> <span class="hljs-keyword">users</span> (<span class="hljs-keyword">name</span>, age, surname) <span class="hljs-keyword">VALUES</span>
(<span class="hljs-string">'Alice'</span>, <span class="hljs-number">25</span>, <span class="hljs-string">'Smith'</span>),
(<span class="hljs-string">'Bob'</span>, <span class="hljs-number">30</span>, <span class="hljs-string">'Johnson'</span>),
(<span class="hljs-string">'Charlie'</span>, <span class="hljs-number">35</span>, <span class="hljs-string">'Williams'</span>),
(<span class="hljs-string">'David'</span>, <span class="hljs-number">40</span>, <span class="hljs-string">'Jones'</span>),
(<span class="hljs-string">'Emma'</span>, <span class="hljs-number">22</span>, <span class="hljs-string">'Brown'</span>),
(<span class="hljs-string">'Frank'</span>, <span class="hljs-number">28</span>, <span class="hljs-string">'Davis'</span>),
(<span class="hljs-string">'Grace'</span>, <span class="hljs-number">33</span>, <span class="hljs-string">'Miller'</span>),
(<span class="hljs-string">'Henry'</span>, <span class="hljs-number">45</span>, <span class="hljs-string">'Wilson'</span>),
(<span class="hljs-string">'Isabella'</span>, <span class="hljs-number">27</span>, <span class="hljs-string">'Moore'</span>),
(<span class="hljs-string">'Jack'</span>, <span class="hljs-number">32</span>, <span class="hljs-string">'Taylor'</span>),
(<span class="hljs-string">'Kate'</span>, <span class="hljs-number">29</span>, <span class="hljs-string">'Anderson'</span>),
(<span class="hljs-string">'Liam'</span>, <span class="hljs-number">38</span>, <span class="hljs-string">'Thomas'</span>),
(<span class="hljs-string">'Mia'</span>, <span class="hljs-number">26</span>, <span class="hljs-string">'Jackson'</span>),
(<span class="hljs-string">'Noah'</span>, <span class="hljs-number">31</span>, <span class="hljs-string">'White'</span>),
(<span class="hljs-string">'Olivia'</span>, <span class="hljs-number">34</span>, <span class="hljs-string">'Harris'</span>),
(<span class="hljs-string">'Patrick'</span>, <span class="hljs-number">37</span>, <span class="hljs-string">'Clark'</span>),
(<span class="hljs-string">'Quinn'</span>, <span class="hljs-number">41</span>, <span class="hljs-string">'Allen'</span>),
(<span class="hljs-string">'Riley'</span>, <span class="hljs-number">36</span>, <span class="hljs-string">'Scott'</span>),
(<span class="hljs-string">'Sophia'</span>, <span class="hljs-number">39</span>, <span class="hljs-string">'Adams'</span>),
(<span class="hljs-string">'Thomas'</span>, <span class="hljs-number">42</span>, <span class="hljs-string">'Lee'</span>),
(<span class="hljs-string">'Uma'</span>, <span class="hljs-number">23</span>, <span class="hljs-string">'Parker'</span>),
(<span class="hljs-string">'Vincent'</span>, <span class="hljs-number">44</span>, <span class="hljs-string">'Robinson'</span>),
(<span class="hljs-string">'Willow'</span>, <span class="hljs-number">43</span>, <span class="hljs-string">'Nelson'</span>),
(<span class="hljs-string">'Xander'</span>, <span class="hljs-number">24</span>, <span class="hljs-string">'Evans'</span>),
(<span class="hljs-string">'Yasmine'</span>, <span class="hljs-number">21</span>, <span class="hljs-string">'Murphy'</span>),
(<span class="hljs-string">'Zoe'</span>, <span class="hljs-number">46</span>, <span class="hljs-string">'Carter'</span>),
(<span class="hljs-string">'Aaron'</span>, <span class="hljs-number">20</span>, <span class="hljs-string">'Baker'</span>),
(<span class="hljs-string">'Bella'</span>, <span class="hljs-number">47</span>, <span class="hljs-string">'Wright'</span>),
(<span class="hljs-string">'Caleb'</span>, <span class="hljs-number">19</span>, <span class="hljs-string">'Garcia'</span>),
(<span class="hljs-string">'Diana'</span>, <span class="hljs-number">48</span>, <span class="hljs-string">'King'</span>),
(<span class="hljs-string">'Ethan'</span>, <span class="hljs-number">50</span>, <span class="hljs-string">'Hall'</span>),
(<span class="hljs-string">'Fiona'</span>, <span class="hljs-number">49</span>, <span class="hljs-string">'Adams'</span>),
(<span class="hljs-string">'Gabriel'</span>, <span class="hljs-number">51</span>, <span class="hljs-string">'Mitchell'</span>),
(<span class="hljs-string">'Hannah'</span>, <span class="hljs-number">52</span>, <span class="hljs-string">'Thompson'</span>),
(<span class="hljs-string">'Ian'</span>, <span class="hljs-number">53</span>, <span class="hljs-string">'Green'</span>),
(<span class="hljs-string">'Julia'</span>, <span class="hljs-number">54</span>, <span class="hljs-string">'Phillips'</span>),
(<span class="hljs-string">'Kevin'</span>, <span class="hljs-number">55</span>, <span class="hljs-string">'Cook'</span>),
(<span class="hljs-string">'Laura'</span>, <span class="hljs-number">56</span>, <span class="hljs-string">'Rivera'</span>),
(<span class="hljs-string">'Michael'</span>, <span class="hljs-number">57</span>, <span class="hljs-string">'Perez'</span>),
(<span class="hljs-string">'Nora'</span>, <span class="hljs-number">58</span>, <span class="hljs-string">'Torres'</span>),
(<span class="hljs-string">'Oscar'</span>, <span class="hljs-number">59</span>, <span class="hljs-string">'Hill'</span>),
(<span class="hljs-string">'Penelope'</span>, <span class="hljs-number">60</span>, <span class="hljs-string">'Young'</span>),
(<span class="hljs-string">'Quentin'</span>, <span class="hljs-number">61</span>, <span class="hljs-string">'Gonzalez'</span>),
(<span class="hljs-string">'Rachel'</span>, <span class="hljs-number">62</span>, <span class="hljs-string">'Hughes'</span>),
(<span class="hljs-string">'Samuel'</span>, <span class="hljs-number">63</span>, <span class="hljs-string">'Turner'</span>),
(<span class="hljs-string">'Tiffany'</span>, <span class="hljs-number">64</span>, <span class="hljs-string">'Parker'</span>),
(<span class="hljs-string">'Ulysses'</span>, <span class="hljs-number">65</span>, <span class="hljs-string">'Ward'</span>),
(<span class="hljs-string">'Victoria'</span>, <span class="hljs-number">66</span>, <span class="hljs-string">'Foster'</span>),
(<span class="hljs-string">'Walter'</span>, <span class="hljs-number">67</span>, <span class="hljs-string">'Stewart'</span>),
(<span class="hljs-string">'Xavier'</span>, <span class="hljs-number">68</span>, <span class="hljs-string">'Wells'</span>),
(<span class="hljs-string">'Yolanda'</span>, <span class="hljs-number">69</span>, <span class="hljs-string">'Bennett'</span>),
(<span class="hljs-string">'Zachary'</span>, <span class="hljs-number">70</span>, <span class="hljs-string">'Gray'</span>),
(<span class="hljs-string">'Arthur'</span>, <span class="hljs-number">71</span>, <span class="hljs-string">'Sullivan'</span>),
(<span class="hljs-string">'Beatrice'</span>, <span class="hljs-number">72</span>, <span class="hljs-string">'Cole'</span>),
(<span class="hljs-string">'Christopher'</span>, <span class="hljs-number">73</span>, <span class="hljs-string">'Morris'</span>),
(<span class="hljs-string">'Danielle'</span>, <span class="hljs-number">74</span>, <span class="hljs-string">'Gutierrez'</span>),
(<span class="hljs-string">'Edward'</span>, <span class="hljs-number">75</span>, <span class="hljs-string">'Perry'</span>),
(<span class="hljs-string">'Felicity'</span>, <span class="hljs-number">76</span>, <span class="hljs-string">'Barnes'</span>),
(<span class="hljs-string">'George'</span>, <span class="hljs-number">77</span>, <span class="hljs-string">'Knight'</span>),
(<span class="hljs-string">'Holly'</span>, <span class="hljs-number">78</span>, <span class="hljs-string">'Bryant'</span>),
(<span class="hljs-string">'Ivan'</span>, <span class="hljs-number">79</span>, <span class="hljs-string">'Reed'</span>),
(<span class="hljs-string">'Jessica'</span>, <span class="hljs-number">80</span>, <span class="hljs-string">'Banks'</span>),
(<span class="hljs-string">'Kenneth'</span>, <span class="hljs-number">81</span>, <span class="hljs-string">'Lopez'</span>),
(<span class="hljs-string">'Lily'</span>, <span class="hljs-number">82</span>, <span class="hljs-string">'Harrison'</span>),
(<span class="hljs-string">'Matthew'</span>, <span class="hljs-number">83</span>, <span class="hljs-string">'Gomez'</span>),
(<span class="hljs-string">'Natalie'</span>, <span class="hljs-number">84</span>, <span class="hljs-string">'Fisher'</span>),
(<span class="hljs-string">'Oliver'</span>, <span class="hljs-number">85</span>, <span class="hljs-string">'Murray'</span>),
(<span class="hljs-string">'Patricia'</span>, <span class="hljs-number">86</span>, <span class="hljs-string">'Marshall'</span>),
(<span class="hljs-string">'Quincy'</span>, <span class="hljs-number">87</span>, <span class="hljs-string">'Dean'</span>),
(<span class="hljs-string">'Rebecca'</span>, <span class="hljs-number">88</span>, <span class="hljs-string">'Gilbert'</span>),
(<span class="hljs-string">'Simon'</span>, <span class="hljs-number">89</span>, <span class="hljs-string">'Wagner'</span>),
(<span class="hljs-string">'Tara'</span>, <span class="hljs-number">90</span>, <span class="hljs-string">'Dunn'</span>),
(<span class="hljs-string">'Ursula'</span>, <span class="hljs-number">91</span>, <span class="hljs-string">'Mcdonald'</span>),
(<span class="hljs-string">'Victor'</span>, <span class="hljs-number">92</span>, <span class="hljs-string">'Pierce'</span>),
(<span class="hljs-string">'Wendy'</span>, <span class="hljs-number">93</span>, <span class="hljs-string">'Gordon'</span>),
(<span class="hljs-string">'Xena'</span>, <span class="hljs-number">94</span>, <span class="hljs-string">'Holmes'</span>),
(<span class="hljs-string">'Yvonne'</span>, <span class="hljs-number">95</span>, <span class="hljs-string">'Henry'</span>),
(<span class="hljs-string">'Zelda'</span>, <span class="hljs-number">96</span>, <span class="hljs-string">'Hunt'</span>),
(<span class="hljs-string">'Andrew'</span>, <span class="hljs-number">97</span>, <span class="hljs-string">'Rose'</span>),
(<span class="hljs-string">'Barbara'</span>, <span class="hljs-number">98</span>, <span class="hljs-string">'Owens'</span>),
(<span class="hljs-string">'Carl'</span>, <span class="hljs-number">99</span>, <span class="hljs-string">'Hudson'</span>),
(<span class="hljs-string">'Daisy'</span>, <span class="hljs-number">100</span>, <span class="hljs-string">'Bishop'</span>);
</code></pre>
<p>E assim concluímos o processo de configuração do Kafka com Debezium, estabelecendo uma estrutura local para monitoramento de operações em bancos de dados legados. Com este ambiente configurado, podemos gerar eventos a partir das alterações realizadas nas tabelas do banco de dados, facilitando a integração e o processamento de dados em tempo real. Se precisar de mais alguma informação ou tiver alguma dúvida, estou à disposição para ajudar!</p>
]]></content:encoded></item><item><title><![CDATA[Padrão Strategy]]></title><description><![CDATA[Imagine que você quer executar operações de diferentes maneiras, mas com o mesmo propósito! Talvez um bom exemplo seja a execução de uma função para diferentes tipos de clientes, ou talvez ter que lidar com vários adquirentes para o mesmo endpoint, p...]]></description><link>https://andresilva.dev/padrao-strategy</link><guid isPermaLink="true">https://andresilva.dev/padrao-strategy</guid><category><![CDATA[Strategy]]></category><category><![CDATA[patterns]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[André Martins]]></dc:creator><pubDate>Wed, 20 Aug 2025 18:20:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1755740206465/43895d52-c271-4deb-b979-2241cbe96841.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Imagine que você quer executar operações de diferentes maneiras, mas com o mesmo propósito! Talvez um bom exemplo seja a execução de uma função para diferentes tipos de clientes, ou talvez ter que lidar com vários adquirentes para o mesmo endpoint, pegando o que está ativo para lidar de forma diferente. Vamos seguir com o exemplo do cliente, será mais fácil de entender.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">enum</span> ClientType
{
    PF,
    PJ,
    FORNECEDOR,
}
<span class="hljs-keyword">class</span> <span class="hljs-title">MensagensService</span> {

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> <span class="hljs-keyword">void</span> <span class="hljs-title">EnviarMensagens</span>(<span class="hljs-params">Cliente cliente</span>)</span> {

        <span class="hljs-keyword">if</span> (ClienteHelper.TypeCliente(cliente) == ClientType.PF) {
            <span class="hljs-comment">// lógica para executar o envio da mensagem para cliente pessoa fisica</span>
        }

        <span class="hljs-keyword">if</span> (ClienteHelper.TypeCliente(cliente) == ClientType.PJ) {
            <span class="hljs-comment">// lógica para executar o envio da mensagem para cliente PJ</span>
        }

        <span class="hljs-keyword">if</span> (ClienteHelper.TypeCliente(cliente) == ClientType.FORNECEDOR) {
            <span class="hljs-comment">// lógica para executar o envio da mensagem para cliente fornecedor</span>
        }

    }
}
</code></pre>
<p>O código acima é muito ruim. Com o passar do tempo, ele se torna ineficiente e confuso. Cada tipo de cliente tem estratégias diferentes para o envio de mensagens, e essas, neste momento, não importam muito. O que importa é que isso tem que ser tratado de forma separada. Existem outras formas de resolver isso, mas hoje estamos falando do strategy.</p>
<h2 id="heading-solucao">Solução</h2>
<p>Uma boa solução seria uma classe que consegue navegar entre cada estratégia, e aqui vamos definir que cada estratégia se trata de cada tipo de envio de mensagem. Vamos chamar essa classe de contexto.</p>
<p>Também precisamos de uma rota (interface) entre a classe de contexto e as estratégias.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">interface</span> <span class="hljs-title">Strategy</span> {
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">Execute</span>(<span class="hljs-params"></span>)</span>;
}

<span class="hljs-keyword">class</span> <span class="hljs-title">EnvioMensagemPF</span> : <span class="hljs-title">Strategy</span> {
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Execute</span>(<span class="hljs-params"></span>)</span> {
        <span class="hljs-comment">// lógica para executar o envio da mensagem para cliente pessoa fisica</span>
    }
}

<span class="hljs-keyword">class</span> <span class="hljs-title">EnvioMensagemPJ</span> : <span class="hljs-title">Strategy</span> {
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Execute</span>(<span class="hljs-params"></span>)</span> {
        <span class="hljs-comment">// lógica para executar o envio da mensagem para cliente PJ</span>
    }
}

<span class="hljs-keyword">class</span> <span class="hljs-title">EnvioMensagemFornecedor</span> : <span class="hljs-title">Strategy</span> {
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Execute</span>(<span class="hljs-params"></span>)</span> {
        <span class="hljs-comment">// lógica para executar o envio da mensagem para cliente FORNECEDOR</span>
    }
}

<span class="hljs-keyword">class</span> <span class="hljs-title">Context</span> {
    <span class="hljs-keyword">private</span> Strategy Strategy {<span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>;}

     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Context</span>(<span class="hljs-params">Strategy strategy</span>)</span> {
        Strategy = strategy;
     }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Execute</span>(<span class="hljs-params"></span>)</span> {
        Console.WriteLine(<span class="hljs-string">"executando strategy"</span>);
        Strategy.Execute();
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">SetStrategy</span>(<span class="hljs-params">Strategy strategy</span>)</span> {
        Strategy = strategy;
    }
}
</code></pre>
<p>A partir de agora, ficou bem mais tranquilo adicionar lógica e comportamento de forma separada para cada método <code>Execute</code> de cada tipo de envio.</p>
<h2 id="heading-factory">Factory</h2>
<p>Vamos definir uma factory para não precisar lidar com esses ifs de forma excessiva.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">class</span> <span class="hljs-title">EnvioMensagemFactory</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> Dictionary&lt;ClientType, IStrategy&gt; _strategies;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">EnvioMensagemFactory</span>(<span class="hljs-params"></span>)</span>
    {
        _strategies = <span class="hljs-keyword">new</span> Dictionary&lt;ClientType, IStrategy&gt;
        {
            { ClientType.PF, <span class="hljs-keyword">new</span> EnvioMensagemPF() },
            { ClientType.PJ, <span class="hljs-keyword">new</span> EnvioMensagemPJ() },
            { ClientType.FORNECEDOR, <span class="hljs-keyword">new</span> EnvioMensagemFornecedor() }
        };
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> IEnvioMensagemStrategy <span class="hljs-title">GetStrategy</span>(<span class="hljs-params">ClientType tipoCliente</span>)</span>
    {
        <span class="hljs-keyword">if</span> (_strategies.TryGetValue(tipoCliente, <span class="hljs-keyword">out</span> <span class="hljs-keyword">var</span> strategy))
            <span class="hljs-keyword">return</span> strategy;

        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Exception(<span class="hljs-string">"Tipo de cliente não suportado"</span>);
    }
}
</code></pre>
<h2 id="heading-executando-strategy">Executando strategy</h2>
<pre><code class="lang-csharp"><span class="hljs-keyword">class</span> <span class="hljs-title">MensagensService</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> EnvioMensagemFactory _factory;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MensagensService</span>(<span class="hljs-params"></span>)</span>
    {
        _factory = <span class="hljs-keyword">new</span> EnvioMensagemFactory();
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">EnviarMensagens</span>(<span class="hljs-params">Cliente cliente</span>)</span>
    {
        <span class="hljs-keyword">var</span> tipoCliente = ClienteHelper.TypeCliente(cliente);
        <span class="hljs-keyword">var</span> strategy = _factory.GetStrategy(tipoCliente);

        <span class="hljs-keyword">await</span> strategy.EnviarMensagem(cliente);
    }
}
</code></pre>
<p>Gostou do resultado? Esse tipo de implementação melhora muito a leitura e a manutenibilidade do código.</p>
]]></content:encoded></item><item><title><![CDATA[Criando primeiro endpoint com Spring Boot]]></title><description><![CDATA[Start
Olá, talvez o ecossistema spring seja o mais completo da atualidade, esse ecossistema cada vez vem melhorando e refinando, temos um mundo de empresas que o utilizam e quando falamos de microserviços spring é fantástico.
Por onde podemos começar...]]></description><link>https://andresilva.dev/criando-primeiro-endpoint-com-spring-boot</link><guid isPermaLink="true">https://andresilva.dev/criando-primeiro-endpoint-com-spring-boot</guid><category><![CDATA[Springboot]]></category><category><![CDATA[Spring]]></category><category><![CDATA[Java]]></category><dc:creator><![CDATA[André Martins]]></dc:creator><pubDate>Sun, 19 Dec 2021 21:45:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1639950164922/w4BSCGvde.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-start">Start</h3>
<p>Olá, talvez o ecossistema spring seja o mais completo da atualidade, esse ecossistema cada vez vem melhorando e refinando, temos um mundo de empresas que o utilizam e quando falamos de microserviços spring é fantástico.</p>
<p>Por onde podemos começar a utilização do spring, bem antigamente era bem complicado para configurar o spring como aplicação para se trabalhar com web, eu mesmo sofri um pouco com xml na epoca da faculdade rsrsrs, mas o pessoal do spring teve uma ideia muito boa, visto que a maioria das aplicações tem a mesma configuração, por que não utilizar configuração por convenção? o spring boot ajuda nisso, com seus componentes pré configurados ficou muito fácil sair utilizando todo poder que o ecosistema spring nos dá.</p>
<h3 id="heading-instalando-plugin-vs-code">instalando plugin vs-code</h3>
<p>Se você já tem uma IDE configurada pode pular essa parte, agora se está começando poderá instalar esses plugins no vs-code
https://marketplace.visualstudio.com/items?itemName=Pivotal.vscode-boot-dev-pack
A partir de agora você está apto a rodar projetos spring no vs-code, não tem mistério, se preferir utilizar o https://spring.io/tools ou https://www.jetbrains.com/pt-br/idea/ fique a vontade pois são ótimas escolhas também.</p>
<h3 id="heading-start-project">Start project</h3>
<p>Hoje temos o https://start.spring.io/ e vale muito a pena conhecer, esse site tem a capacidade de gerar projetos para a plataforma spring.</p>
<p>Mas vamos seguir o caminho de pegar um projeto pré configurado, onde podemos apenas escrever a entidade, controller e repositorio, mas se você pensou, eu não sei o que é isso, fica tranquilo que no caminho você vai aprender.</p>
<p>Link para o repositorio pré configurado: https://github.com/andremartds/spring_boot_pre_configurado</p>
<h3 id="heading-estrutura-do-projeto">Estrutura do projeto</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1639945349260/bBTqZWKWyo.png" alt="Screenshot from 2021-12-19 17-22-03.png" /></p>
<p>Se você já entende dos pakages do java, esse entendimento vai ser tranquilo, basicamente temos:
<strong>main</strong>: pasta principal do projeto
<strong>java</strong>: sendo nosso contexto da aplicação java
<strong>com/andremartds/cadastro</strong>: contexto do nosso endpoint</p>
<p>Logo dentro de cadastro temos, controllers, exceptionHandler, model, repository, services e nosso ponto de entrada da aplicação que no caso é esse arquivo <strong>App.java</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1639945596488/Hd-k_s-ju4.png" alt="code.png" /></p>
<p>Perceba o quanto é simples esse arquivo, ele apenas chama a classe do SpringApplication e nossa aplicação será inicializada, não vamos entrar em detalhes mais profundos nesse ponto, precisamos subir nossa api o mais rápido possível.</p>
<h3 id="heading-entidade-ou-model">Entidade ou Model</h3>
<p>No java assim como em outras linguágens podemos ter representações de tabelas do banco de dados em nossa aplicação, e isso facilita o dia dia, imagine que pra acessar seu banco de dados sempre tivesse que escrever querys na mão, quão verboso sua api seria, é claro que as vezes é necessário, sem mais delongas vamos a nossa entidade de pessoa.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1639945900863/6Kv7hzcNj.png" alt="pessoa-entity.png" /></p>
<p>Nada demais, aqui estamos mapeando nossa entidade com seus atributos, vamos passar por cada um deles</p>
<h3 id="heading-codigo">codigo</h3>
<p>O  código anotamos com a anotação <code>@Id</code> e <code>@GeneratedValue(strategy = GenerationType.IDENTITY)</code> resumindo essas anotação farão com que seja criado o codigo no banco de dados, esse código será auto incrementável, ou seja, 1, 2, 3...</p>
<h3 id="heading-nome">nome</h3>
<p>Para o nome temos logo acima do mesmo, <code>@NotNull</code> essa anotação faz a uma validação onde não poderá ser um campo indefinido, sem valor ou nulo. Temos também o <code>@size(min=3, max=50)</code> com isso só pode ter o mínimo de caracteres de 3 a 50</p>
<h3 id="heading-endereco">Endereco</h3>
<p>Aqui temos uma pequena curiosidade, no caso estamos utilizando o <code>@Embedded</code> estamos instruindo o código a aceitar esse embedável, que estamos tratando em outra classe.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1639946500391/BfVSZuyhR.png" alt="endereco-entity.png" /></p>
<p>Nessa classe anotamos a mesma com <code>@Embeddable</code> ou seja ela poderá ser embedada por um <code>@Embedded</code> pegou a ideia?
Dessa forma estamos colocando na mesma tabela do banco de dados, porém estamos trabalhando com responsabilidades separadas no codigo.</p>
<h3 id="heading-ativo">ativo</h3>
<p>Por último temos o ativo que se trata de um boleano, não tem mistérios.</p>
<h3 id="heading-repository">Repository</h3>
<p>Logo a baixo da pasta model temos a pasta Repository, e uma das maiores vantágens de se trabalhar com o padrão repository é  o fato de podermos extender todo os métodos do SpringDataJpa, você pode pensar, que vantágem tem isso? com o SpringDataJpa você passa a ter super poderes e é muito provável que ele resolva a maioria de suas chamadas ao banco de dados.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1639946925859/HTfr-9coU.png" alt="repository.png" /></p>
<p>Tão simples quanto isso, basta criar a interface extender JpaRepository Passando Pessoa e o tipo de seu Id, no caso Long.</p>
<h3 id="heading-exceptionhandler">ExceptionHandler</h3>
<p>não vou me alongar muito na explicação do exceptionHandler, vamos resumir em uma frase.
Responsável por capturar as exceções e tratá-las, deixando mais limpo, service ou controller.</p>
<p>Na verdade não precisava nesse primeiro momento trabalharmos com esse tipo de captura de exception, vou deixar o código mais como exemplo mesmo, hehe.</p>
<h3 id="heading-controller">Controller</h3>
<p>Controller ou Resource é onde vamos trabalhar com toda a camada dos dados que entram para o nosso endpoint, nesse caso que entram por '/pessoas'</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1639947265256/WDvbCoDYs.png" alt="pessoa.png" /></p>
<p>De cara vemos algumas coisas interessantes, a primeira é como o spring trabalha para dizer que esse arquivo é um controller, então adicionamos a anotação <code>@RestController</code> e logo abaixo temos a <code>@RequestMapping("/pessoas")</code> que é responsável por adicionar a URI de entrada para esse endpoint</p>
<h3 id="heading-autowired">Autowired</h3>
<p>Utilizamos essa anotação para injetarmos algo no contexto do spring, e nesse caso estamos injetando aquele repository que terá todos os métodos para utilizarmos e também estamos injetando o service de pessoas que já vamos detalhar.</p>
<h3 id="heading-todos-usuarios">Todos Usuarios</h3>
<p>Esse método tem a reponsabilidade de retornar todos os usuários, nesse caso estamos utilizando os artificios do nosso repository para trazer tudo, e já estamos jogando isso para uma lista de pessoas.</p>
<h3 id="heading-buscar-por-codigo">Buscar Por Código</h3>
<p>Esse metodo tem a finalidade de trazer uma pessoa por seu código, perceba que adicionamos o <code>@GetMapping("/{codigo}")</code> e dessa forma vamos estar prontos para pegar uma variável com o <code>@PathVariable</code> que no caso foi o proprio codigo, depois utilizamos os recursos adicionados no java 8 para fazer o map com uma lambda, trazendo todos os registros se ok e se não nada foi encontrado.</p>
<h3 id="heading-adicionando-pessoa">Adicionando Pessoa</h3>
<p>Esse método vamos adicionar uma pessoa no nosso banco de dados, perceba que nos argumentos da função estamos passando <code>@valid</code> essa anotação fará com que aquelas validações que colocamos dentro da entidade sejam verificadas, no final retornamos o ResponsyEntity passando o Status http como create e o body que foi a própria pessoa salva.</p>
<h3 id="heading-remover-pessoa">Remover Pessoa</h3>
<p>Esse método tem por finalidade remover a pessoa selecionada, pegamos o codigo só que agora com o <code>@deleteMapping("/{codigo}")</code> e vamos dar a resposta com o httpStatus no content assim, não irá retornar nada do que foi removido, que é o correto, já que o registro não existe mais.</p>
<h3 id="heading-atualizar-pessoa-e-atualizar-pessoa-parcialmente">Atualizar Pessoa e Atualizar pessoa parcialmente</h3>
<p>Para atualizar uma pessoa também é muito simples, só que nesse caso vamos utilzar o service, que no dia a dia é bem mais comun, afinal não dá pra deixar regras de negócio na camada do controller, então passamos para nosso service no método atualiza pessoa o codigo e a pessoa que veio na requisição put.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1639948338261/9u419q4SF.png" alt="service.png" /></p>
<p>No caso da atualização de pessoa, estamos fazendo o trabalho duro no service, estamos seguindo o mesmo comportamento anterior dos outros métodos só que no service retornando para o controller, imagine se sua aplicação tivesse várias validações para atualizar uma pessoa, não seria justo nem bonito deixar o código no controller.</p>
<p>Por fim temos a atualização com o patch, atualizar com esse verbo significa que será uma atualização parcial, isso é sempre bom quando possível afinal estamos poupando recursos, no caso desse método trabalhamos com o mesmo comportamento, recebemos o id em <code>@patchMapping("/{codigo}/ativo")</code> só que a diferença é que estamos enviando no body, true ou false, dessa forma setamos apenas esse valor para a entidade.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1639948693844/tJobXT-3j.png" alt="Screenshot from 2021-12-19 18-17-44.png" /></p>
<p>A importação dos arquivos do postman estão zipados dentro do projeto. </p>
<h1 id="heading-obrigado-pela-leitura">obrigado pela leitura.</h1>
]]></content:encoded></item><item><title><![CDATA[iniciando rápido com Docker [BR]]]></title><description><![CDATA[Motivo
Muitas pessoas tem dificuldades para iniciar com docker, mas na verdade se elas tem domínio das ferramentas que já trabalham no seu dia dia, docker vai ser mais um detalhe, bom acho que todos já estão cansados de saber quão bom é trabalhar com...]]></description><link>https://andresilva.dev/iniciando-rapido-com-docker-br</link><guid isPermaLink="true">https://andresilva.dev/iniciando-rapido-com-docker-br</guid><category><![CDATA[Docker]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[André Martins]]></dc:creator><pubDate>Sat, 16 Oct 2021 20:24:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1634415965581/x8V0T2pYp.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="motivo">Motivo</h3>
<p>Muitas pessoas tem dificuldades para iniciar com docker, mas na verdade se elas tem domínio das ferramentas que já trabalham no seu dia dia, docker vai ser mais um detalhe, bom acho que todos já estão cansados de saber quão bom é trabalhar com docker e quão flexível isso pode se tornar, alem do mais é amplamente utilizado em muitas empresas e acaba se tornando indispensável para o currículo de um desenvolvedor, então deixemos de lado a introdução e vamos direto aos pontos.</p>
<h3 id="comandos-uteis-para-seu-dia-dia">Comandos úteis para seu dia dia</h3>
<h3 id="rodando">Rodando</h3>
<pre><code class="lang-go"><span class="hljs-comment">// quer trazer uma imagem para sua máquina e já sair rodando? esse é o comando</span>
docker run ubuntu

<span class="hljs-comment">// faz o download de uma imagem mas não excuta</span>
docker pull nome_usuario/nome_image
</code></pre>
<h3 id="containers">Containers</h3>
<pre><code class="lang-go"><span class="hljs-comment">// listando todos os containers que estiverem ativos</span>
docker ps

<span class="hljs-comment">// listando todos os ids dos containers, ativos</span>
docker ps -q

<span class="hljs-comment">// listando todos os ids dos containers, ativos</span>
docker ps -aq

<span class="hljs-comment">// iniciando um container</span>
docker start name_container

<span class="hljs-comment">// para todos os containers ativos de uma só vez</span>
docker stop $(docker ps -aq)

<span class="hljs-comment">// rodando um container atrelado ao seu terminal</span>
docker run -it name_image

<span class="hljs-comment">// para parar um container</span>
docker stop (name or id)

<span class="hljs-comment">// removendo um container de forma forçada</span>
docker rm (id or name) -f

<span class="hljs-comment">// removendo todos os containers parados</span>
docker container prune

<span class="hljs-comment">// rodando um container com uma porta e nome e de forma desatrelada ao terminal</span>
docker run -d -p <span class="hljs-number">80</span>:<span class="hljs-number">8080</span> --name server nginx:latest

<span class="hljs-comment">// parando um container e removendo e o removendo</span>
docker-compose down --rmi all

<span class="hljs-comment">// acessando seu container</span>
docker exec -it name-container sh
</code></pre>
<h3 id="imagens">Imagens</h3>
<pre><code class="lang-go"><span class="hljs-comment">//lista todas as imagens</span>
docker image ls

<span class="hljs-comment">//lista todas as imagens</span>
docker image

<span class="hljs-comment">// remove todas as imagens</span>
docker rmi $(docker images -q)

<span class="hljs-comment">// remove uma imagem</span>
docker rmi name_image

<span class="hljs-comment">// limpando tudo</span>
docker system prune
</code></pre>
<h3 id="network">Network</h3>
<pre><code class="lang-go"><span class="hljs-comment">// Adicionando rede</span>
docker network create --driver bridge local

<span class="hljs-comment">// removendo todas as redes</span>
docker network prune
</code></pre>
<h3 id="outros">Outros</h3>
<pre><code class="lang-go"><span class="hljs-comment">// Copiando excema de uma base mysql</span>
docker exec container_mysql_name /usr/bin/mysqldump -u root --password=root schema &gt; backup.sql

<span class="hljs-comment">// Rodando um postgresql sem dockerfile</span>
docker run --name postgres11 -e POSTGRES_PASSWORD=docker -p <span class="hljs-number">5432</span>:<span class="hljs-number">5432</span> -d postgres:<span class="hljs-number">11</span>

<span class="hljs-comment">// rodando um mongo sem dockerfile</span>
docker run --name mongo -p <span class="hljs-number">27017</span>:<span class="hljs-number">27017</span> -d -t mongo

<span class="hljs-comment">// rodando um mysql sem dockerfile</span>
docker run --detach --name=mysql8 -p <span class="hljs-number">3306</span>:<span class="hljs-number">3306</span>  --env=<span class="hljs-string">"MYSQL_ROOT_PASSWORD=docker"</span> mysql:<span class="hljs-number">8.0</span><span class="hljs-number">.22</span>
</code></pre>
<h3 id="docker-register">Docker Register</h3>
<p>Imagine o cenário, precisamos configurar uma imagem pessoal para subir em um container em determinado servidor, com o doker hub podemos facilmente ter images pessoais privadas(plano não gratuito no docker hub), assim podemos usa-las quando e onde quisermos, grandes datacenter como, gcp, amazon e azure também vão ter seus próprios registers, basta termos nosso register privado lá e conseguiremos ter nossas imagens privadas para subir em nosso servdor remoto.</p>
<h3 id="binds-e-mountsvolumes">Binds e mounts/volumes</h3>
<p>Muitas vezes removemos os containers após o uso. </p>
<p>É muito comum usar o container e apagá-lo após o uso, dessa forma os dados desses container são perdidos e nesse ponto que os volumes ou mounts permitem salvar dados fora de um container.</p>
<p>Volumes são usados para os dados não serem removidos ao paramos nosso container, trata-se de um mapeamento entre seu host (computador de trabalho) e container, na maioria dos projetos que trabalhamos em ambiente de dev costumamos fazer um apontamento entre nossa maquina e algum container.</p>
<pre><code class="lang-go">docker run -d --name nginx -v ~/ti/testdocker/html:/usr/share/nginx/html -p <span class="hljs-number">8080</span>:<span class="hljs-number">80</span> nginx
</code></pre>
<p>No exemplo acima apontamos um volume de nossa maquina local por meio da tag -v  para dentro da pasta do nginx, dessa forma se perdemos nossa imagem o conteúdo está salvo em nosso host.</p>
<p>A forma mais atual de se trabalhar com volumes é utilizando mounts, um exemplo de diferença entre volumes e mouts é que volumes criam pastas em nosso host mesmo que essas não existam, mounts não.</p>
<pre><code class="lang-go">docker run -d --name nginx --mount <span class="hljs-keyword">type</span>=bind, source=/Users/andremartds/ti/testdocker/html,target=/usr/share/nginx/html -p <span class="hljs-number">8080</span>:<span class="hljs-number">80</span> nginx

docker run -d --name nginx --mount <span class="hljs-keyword">type</span>=bind, source=<span class="hljs-string">"$(pwd)"</span>,target=/usr/share/nginx/html -p <span class="hljs-number">8080</span>:<span class="hljs-number">80</span> nginx
</code></pre>
<p>Caso você utilize $(pwd) isso vai conseguir pegar o diretório absoluto de onde você está no momento.</p>
<h3 id="volumes">Volumes</h3>
<p>Pode ser que precisemos ter um volume centralizado em nosso host e queremos apontar esses dados para um ou mais containers, nesse caso tudo que for criado em um container será apontado para os outros que compartilham desse type.</p>
<p>requer estar na mesma rede*</p>
<pre><code class="lang-go"><span class="hljs-comment">// comandos</span>
docker volume

<span class="hljs-comment">// criando nosso volume</span>
docker volume create myvolume

<span class="hljs-comment">// lista todos os volumes existentes</span>
docker volume ls

<span class="hljs-comment">// removendo um volume</span>
docker volume prune (hash volume)

<span class="hljs-comment">// inspecionando um volume</span>
docker volume inspect myvolume
</code></pre>
<h3 id="criando-e-utilizando-volumes">Criando e utilizando volumes</h3>
<pre><code class="lang-go"><span class="hljs-comment">// cria um volume</span>
docker volume create myvolue

<span class="hljs-comment">// rodando uma imagem e atrelando nosso novo volume com -v</span>
docker run -d -p <span class="hljs-number">8082</span>:<span class="hljs-number">80</span> --name nginx24 -v myvolume:/app nginx
<span class="hljs-comment">// ou</span>
docker run -d -p <span class="hljs-number">8080</span>:<span class="hljs-number">80</span> --name nginx1 --mount <span class="hljs-keyword">type</span>=volume,source=myvolume,target=/app nginx
<span class="hljs-comment">//e</span>
docker run -d -p <span class="hljs-number">8081</span>:<span class="hljs-number">80</span> --name nginx2 --mount <span class="hljs-keyword">type</span>=volume,source=myvolume,target=/app nginx
</code></pre>
<h3 id="acessando-e-alterando-arquivos-de-um-container">Acessando e alterando arquivos de um container</h3>
<pre><code class="lang-go"> <span class="hljs-comment">//lista os diretorios da pasta root do container</span>
docker exec nginx ls

 <span class="hljs-comment">// acessa o container com nosso bash local</span>
docker exec nginx -it bash
</code></pre>
<p>Agora que acessamos nosso container vamos alterar o arquivo index do nginx, caminho: cd /usr/share/nginx/html</p>
<p>sudo nano index.html</p>
<p>Perceba o conceito images, elas são IMUTÁVEIS ou seja, caso nosso container seja removido ao reutilzarmos a imagem que temos em nossa máquina a mesma virá sem as alterações que acabamos de fazer</p>
<h3 id="dicas-adicionais">Dicas adicionais</h3>
<p>caso você esteja trabalhando no linux ou mac você poderá adicionar em seu .bashrc ou zshrc alguns atalhos para executar seus comandos</p>
<pre><code class="lang-go">alias d=<span class="hljs-string">"docker"</span>
alias dcu=<span class="hljs-string">"docker-compose up"</span>
alias dd=<span class="hljs-string">"docker-compose up -d"</span>
</code></pre>
<p>agora é só sair utilizando as abreviações na hora de rodar seus comandos docker.</p>
]]></content:encoded></item><item><title><![CDATA[Guia de sobrevivência Mysql [BR]]]></title><description><![CDATA[Olá, para iniciarmos com o mysql eu preparei um guia do que um dev back-end costuma lidar no seu dia dia, pricipalmente em aplicações legadas, você vai precisar.
O Banco de dados MYSQL tem por característica salvar dados em arquivos dentro do host at...]]></description><link>https://andresilva.dev/guia-de-sobrevivencia-mysql-br</link><guid isPermaLink="true">https://andresilva.dev/guia-de-sobrevivencia-mysql-br</guid><category><![CDATA[MySQL]]></category><category><![CDATA[SQL]]></category><dc:creator><![CDATA[André Martins]]></dc:creator><pubDate>Sun, 10 Oct 2021 03:25:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633840704164/IDy1nNSQu.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Olá, para iniciarmos com o mysql eu preparei um guia do que um dev back-end costuma lidar no seu dia dia, pricipalmente em aplicações legadas, você vai precisar.</p>
<p>O Banco de dados MYSQL tem por característica salvar dados em arquivos dentro do host atual ou remoto e criar tratativas para esses dados. Para trabalhar com os dados utilizamos estrutura em tabelas que ficam dentro de banco de dados nomeados.</p>
<p><strong>Databases == schemas</strong></p>
<p>Em banco de dados MYSQL temos as <strong>Databases</strong> e <strong>Schemas</strong>, na verdade são sinônimos e podemos pensar neles como agrupadores de tabelas. Por exemplo: a aplicação do comércio do João tem uma base de dados específica que nada mais é do que tabelas relacionadas entre si utilizando um corpo de trabalho, lugar ou schemas.</p>
<p><strong>Qual a finalidade do sql?</strong> Facilitar a manipulação dos dados podendo interagir de forma produtiva. Existem querys sql, funções, triggers e entre outros que vão tratar dados para facilitar a vida de quem lida com esses dados de forma a ser mais fácil inserir, excluir ou atualizar com base nas regras do negócio.</p>
<p><strong>Como criar uma base de dados?</strong></p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">DATABASE</span> padaria_joao;
</code></pre>
<p>Para criar uma base de dados podemos passar o comando <strong>CREATE DATABASE</strong>, e definimos o nome de nossa base de dados, nesse caso criamos uma base de dados <strong>padaraia_joao</strong></p>
<p><strong>Composição de uma tabela</strong></p>
<p><img src="https://user-images.githubusercontent.com/5201283/105640311-2672ec00-5e5c-11eb-979e-410597fb916d.png" alt="Captura de tela de 2021-01-24 13-42-03" /></p>
<p>No exemplo da imagem acima temos uma tabela produtos com as características:</p>
<p><strong>columns</strong>(colunas),</p>
<p><strong>indexes</strong>(índices),</p>
<p><strong>Foreign Keys</strong>(Chaves Estrangeiras),</p>
<p><strong>Triggers</strong> (Gatilhos).</p>
<p>As colunas são os campos a serem preenchidos com seus respectivos dados, como exemplos podemos pensar em: <strong>id, nome e preco</strong> , os índices geralmente se tratam de nossa chave <strong>primária</strong> que em muitas vezes são <strong>incrementais</strong> ou seja, ao ser inserido um dado o proprio MYSQL faz gerêncimento, os indices também podem ser índices não <strong>clusterizados</strong> onde podemos trabalhar para melhorar as consultas em uma tabela muito acessada.</p>
<p>Chaves estrangeiras são índices relacionados ao mundo exterior ou seja, as outras tabelas dentro de sua base de dados.</p>
<p>Os gatilhos geralmente são comportamentos que queremos que nossa tabela faça se determinada ocorrência acontecer <strong>antes</strong> ou <strong>depois</strong> de uma execução. Por exemplo, temos uma tabela cliente e temos uma tabela mensalidades, sempre que um cliente é inserido podemos criar um gatilho para ser disparado e iniciar a mensalidade com zero dentro da tabela mensalidade, sem uma linha de código no backend da aplicação.</p>
<p><strong>Corpo de uma tabela</strong></p>
<p>Você pode imaginar uma tabela como uma planilha do excel ou libre office, onde temos as colunas e em suas linhas tendo os valores, veja o exemplo abaixo.</p>
<pre><code class="lang-sql"><span class="hljs-comment">-------------------------------------------</span>
id| nome                   | idade   |
<span class="hljs-comment">-------------------------------------------</span>
1 | André Martins          | 150     |
2 | Bia Martins            | 11      |
</code></pre>
<p>as colunas são id, nome e idade. os valores são os dados embaixo de cada titulo de coluna.</p>
<h1 id="heading-sessao-de-comandos">Sessão de comandos</h1>
<p><strong>Criação de um tabela</strong></p>
<pre><code class="lang-sql"><span class="hljs-keyword">create</span> <span class="hljs-keyword">table</span> estudo_mysql.teste(
    <span class="hljs-keyword">id</span> <span class="hljs-built_in">int</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span> auto_increment,
    nome <span class="hljs-built_in">varchar</span>(<span class="hljs-number">90</span>) <span class="hljs-keyword">not</span> <span class="hljs-literal">null</span>,
    primary <span class="hljs-keyword">key</span> (<span class="hljs-string">`id`</span>));
</code></pre>
<p>No exemplo acima criamos uma tabela com o nome teste que está dentro da base de dados estudo_mysql e tem os campos <strong>id</strong> e <strong>nome</strong>, sendo que o id é auto incrementável, não podendo ser nulo e o nome é do tipo varchar suportando até 90 caracteres, também definimos a chave primária sendo o id.</p>
<p><strong>Como criar um relacionamento entre duas tabelas</strong></p>
<p>Acredito que poucas pessoas façam esse tipo de operação sem a ajuda de uma interface gráfica, mas de qualquer forma irei deixar o registro de como fazer.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-string">`testes`</span>.<span class="hljs-string">`produtos`</span> (
  <span class="hljs-string">`id`</span> <span class="hljs-built_in">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span> AUTO_INCREMENT,
  <span class="hljs-string">`nome`</span> <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">45</span>) <span class="hljs-literal">NULL</span>,
  <span class="hljs-string">`id_categoria`</span> <span class="hljs-built_in">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>),
  <span class="hljs-keyword">INDEX</span> <span class="hljs-string">`fk_categoria_idx`</span> (<span class="hljs-string">`id_categoria`</span> <span class="hljs-keyword">ASC</span>) <span class="hljs-keyword">VISIBLE</span>,
  <span class="hljs-keyword">CONSTRAINT</span> <span class="hljs-string">`fk_categoria`</span>
    <span class="hljs-keyword">FOREIGN</span> <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id_categoria`</span>)
    <span class="hljs-keyword">REFERENCES</span> <span class="hljs-string">`testes`</span>.<span class="hljs-string">`categorias`</span> (<span class="hljs-string">`id`</span>)
    <span class="hljs-keyword">ON</span> <span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">CASCADE</span>
    <span class="hljs-keyword">ON</span> <span class="hljs-keyword">UPDATE</span> <span class="hljs-keyword">NO</span> <span class="hljs-keyword">ACTION</span>);
</code></pre>
<p>No exemplo acima iremos destacar que criamos um INDEX com o nome <strong>fk_categoria_idx</strong> que tem uma referência para a coluna <strong>id_categoria</strong>, declaramos que ela é visivel, também declaramos a CONSTRAINT (limitação em tradução literal) que é chamada de <strong>fk_categoria</strong>, por fim nossa <strong>FOREING_KEY</strong> que de fato é onde iremos posteriormente atribuir os resultados. Sempre que fizermos um delete de uma categoria por termos colocado <strong>ON DELETE CASCASE</strong> na tabela de produtos o MYSQL irá excluir todos os produtos relacionados a uma categoria, assim não existirão dados mortos em nosso banco, já no update não colocamos nenhuma ação para ser feita.</p>
<p><strong>Adicionando colunas a uma tabela</strong> Para adicionar uma coluna em MYSQL precisamos alterar uma tabela existente, vamos utilizar a tabela de produtos adicionando a coluna preco.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> produtos <span class="hljs-keyword">ADD</span> <span class="hljs-keyword">COLUMN</span> preco <span class="hljs-built_in">decimal</span>(<span class="hljs-number">10</span>,<span class="hljs-number">2</span>) <span class="hljs-keyword">default</span> <span class="hljs-number">0.0</span>;
</code></pre>
<p>Utilizamos no exemplo o ALTER TABLE passando o nome da tabela e adicionando uma coluna <strong>preco</strong>, note que aplicamos o <strong>default</strong> com o valor 0.0, nesse caso todos os registros que já existam terão o valor padrão 0.0 e como não definimos essa coluna como NOT NULL quando não inserido nada o valor padrão será 0.0</p>
<p><strong>Modificando tipo de dado de uma coluna existente</strong></p>
<p>Para modificar um tipo de uma coluna existente vamos aplicar na tabela produtos, alterando o valor preco para uma string que suporta 45 caracteres.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> produtos <span class="hljs-keyword">modify</span> <span class="hljs-keyword">COLUMN</span> preco <span class="hljs-built_in">varchar</span>(<span class="hljs-number">45</span>) <span class="hljs-keyword">default</span> <span class="hljs-string">'novo_valor'</span>;
</code></pre>
<p>O que já existe na tabela <strong>não será alterado</strong>, porém toda inserção nova que não tiver valores irá atribuir o novo valor padrão 'novo_valor'</p>
<p><strong>Adicionando em uma tabela</strong></p>
<p><strong>inserção única</strong></p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> produtos (nome, preco, descricao) <span class="hljs-keyword">values</span> (<span class="hljs-string">'Testes de primeira inserção'</span>, <span class="hljs-number">100.00</span>, <span class="hljs-string">'descricao do produto'</span>);
</code></pre>
<p><strong>inserção em massa</strong></p>
<pre><code class="lang-sql"><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> tabela(campo1, campo2) <span class="hljs-keyword">values</span> (<span class="hljs-string">"valor 1"</span>, <span class="hljs-number">1</span>), (<span class="hljs-string">"valor 2"</span>, <span class="hljs-number">2</span>), (<span class="hljs-string">"valor 3"</span>, <span class="hljs-number">3</span>);
</code></pre>
<p>Pra inserir em uma tabela precisamos passar o comando <strong>insert</strong> <strong>into</strong> o nome da tabela, seus campos e após isso os <strong>values</strong>(valores) que vem precedido da palavra reservada <strong>values</strong>, note que é preciso respeitar cada tipo de valor que será inserido em sua ordem, no caso da tabela de produtos temos nome sendo <strong>varchar</strong>, preco sendo <strong>decimal (10,2)</strong> e temos a descrição sendo <strong>text</strong>.</p>
<p>caso queira estudar mais sobre tipos de dados para mysql segue um link da documentação oficial</p>
<p>https://dev.mysql.com/doc/refman/8.0/en/data-types.html</p>
<p><strong>Seleção de dados de uma tabela</strong></p>
<p>Para trabalhar com recuperação de dados temos muitas formas a partir do <strong>select</strong>, veja alguns exemplos abaixo:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> pessoa;
</code></pre>
<p>Esse comando seleciona todos os campos da tabela pessoa.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> pessoa <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">id</span>=<span class="hljs-number">1</span>;
</code></pre>
<p>Esse comando seleciona todos os campos de uma pessoa selecionada a partir de uma id passado, perceba que a palavra reservada <strong>where</strong> é onde passamos esse valor.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">where</span> preco &lt;= <span class="hljs-number">100</span>;
</code></pre>
<p>Podemos selecionar todos os produtos desde que (<strong>where</strong>) o preco for menor ou igual a 100</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> preco [<span class="hljs-keyword">desc</span> || <span class="hljs-keyword">asc</span>]
</code></pre>
<p>Agora imagine que você gostaria de trazer todos os produtos com preços por ordem ascendente ou descendente, podemos fazer isso com o <strong>order by</strong> passando a coluna que queremos.</p>
<p><strong>Apelidos em colunas de tabelas</strong></p>
<p>Utilizamos apelidos em colunas para apresentar de uma forma diferente</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> nome <span class="hljs-keyword">as</span> <span class="hljs-string">`Nome do Produto`</span>, preco <span class="hljs-keyword">as</span> <span class="hljs-string">`Preço do produto`</span> <span class="hljs-keyword">from</span> produtos;
</code></pre>
<p>dessa forma alteramos a apresentação das colunas de uma tabela.</p>
<p><strong>Seleção IN</strong></p>
<p>Podemos ter a necessidade de trazer vários produtos com ids passados mas ao mesmo tempo deixar de fora outros, vejamos um exemplo:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> produtos <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">IN</span> (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>);
</code></pre>
<p>Muitas vezes queremos trazer dados de tabelas relacionadas e montamos geralmente a partir de <strong>joins</strong>, mas podemos utilizar a cláusula <strong>IN</strong> para performar melhor em consultas que frequentemente acontecem.</p>
<p>Exemplo: tabela <strong>produto</strong> e tabela <strong>categoria</strong> sendo que um produto tem um relacionamento de n-1 com categoria (n produtos podem estar na mesma categoria), ou seja uma categoria pode ter vários produtos.</p>
<p><strong>tabela de produto campos:</strong><code>id, nome, preco, id_categoria(sendo fk)</code></p>
<p><strong>tabela de categoria campos:</strong><code>id, nome, descricao</code></p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">where</span> id_categoria <span class="hljs-keyword">in</span>(
    <span class="hljs-keyword">select</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">from</span> categorias <span class="hljs-keyword">where</span> nome <span class="hljs-keyword">like</span> <span class="hljs-string">'frutas'</span>
);
</code></pre>
<p>Dessa forma percebemos que podemos trazer todos os produtos que estão em uma determinada categoria que selecionamos a partir de um nome.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">where</span> id_categoria <span class="hljs-keyword">in</span>(
    <span class="hljs-keyword">select</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">from</span> categorias <span class="hljs-keyword">where</span> <span class="hljs-keyword">id</span>=<span class="hljs-number">2</span>
);
</code></pre>
<p>Agora trazemos todos os produtos que estão na categoria de id 2</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">where</span> id_categoria <span class="hljs-keyword">in</span>(
    <span class="hljs-keyword">select</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">from</span> categorias <span class="hljs-keyword">where</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">in</span>(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)
);
</code></pre>
<p>Agora trazemos todos os produtos que estão na categoria 1 e 2</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">where</span> valor &gt; <span class="hljs-number">10</span> <span class="hljs-keyword">and</span> id_categoria <span class="hljs-keyword">in</span>(
    <span class="hljs-keyword">select</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">from</span> categorias <span class="hljs-keyword">where</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">in</span>(<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>)
);
</code></pre>
<p>Agora trazemos todos os produtos com valor maior que 10 e que estão na categoria de id 1, 3 ou 5 perceba o nivel de granularidade que podemos ter em nossas consultas, isso é PODEROSO.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> nome, preco <span class="hljs-keyword">from</span> produtos p <span class="hljs-keyword">where</span> id_categoria <span class="hljs-keyword">IN</span>(
   <span class="hljs-keyword">select</span> <span class="hljs-keyword">id</span> <span class="hljs-keyword">from</span> categorias <span class="hljs-keyword">where</span> (nome=<span class="hljs-string">'frutas'</span> <span class="hljs-keyword">OR</span> nome=<span class="hljs-string">'verduras'</span>) <span class="hljs-keyword">and</span> p.preco &gt;= <span class="hljs-number">15</span>
);
</code></pre>
<p>Nesse exemplo estamos selecionando nome e preco de produtos desde que o id esteja contido no select mais abaixo, onde definimos que a seleção será a partir de nome de uma categoria igual a frutas ou nome igual a verduras, perceba que passamos um apelido para nossa tabela produtos onde utilizamos o mesmo na consulta interna e adicionamos mais uma condição, essa últimas condição poderia ser no primeiro select sem problemas também.</p>
<p><strong>Seleção AND</strong></p>
<p>Podemos utilizar juntamente com o where o and ou or para operar logicamente, veja o exemplo.</p>
<pre><code class="lang-sql"><span class="hljs-comment"># AND</span>
<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">where</span> preco &gt; <span class="hljs-number">100</span> <span class="hljs-keyword">and</span> preco &lt; <span class="hljs-number">112</span>;
<span class="hljs-comment"># OR</span>
<span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">where</span> (valor &gt; <span class="hljs-number">20</span> ou valor &lt; <span class="hljs-number">30</span>);
</code></pre>
<p>No exemplo acima selecionamos na primeira linha de execução todos os produtos que o preço é maior que 100 e menor que 112 e na segunda linha de execução selecionamos todos os produtos que o valor é maior que 10 ou menor que 30</p>
<p><strong>Seleção Like</strong></p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> nome <span class="hljs-keyword">FROM</span> produtos <span class="hljs-keyword">WHERE</span> nome <span class="hljs-keyword">LIKE</span><span class="hljs-string">'m%'</span>;
</code></pre>
<p>No exemplo acima selecionamos um nome de uma tabela chamada produtos desde que nome comece com m e tenha qualquer sequencia de caractéres</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> nome <span class="hljs-keyword">FROM</span> produtos <span class="hljs-keyword">WHERE</span> nome <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">LIKE</span><span class="hljs-string">'m%'</span>;
</code></pre>
<p>Agora é o inverso, onde não temos a letra m sendo a primeira traremos os outros resultados.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> NOME <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">WHERE</span> NOME <span class="hljs-keyword">like</span> <span class="hljs-string">'_a%'</span>;
</code></pre>
<p>Selecionamos todos os produtos desde que contenham a segunda letra sendo <strong>a</strong> seguido de qualquer outro caractere</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> nome <span class="hljs-keyword">FROM</span> produtos <span class="hljs-keyword">WHERE</span> nome <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">LIKE</span> <span class="hljs-string">'_a%'</span>;
</code></pre>
<p>Selecionamos todos os produtos desde que não contenham a segunda letra sendo <strong>a</strong> seguido de qualquer outro caractere</p>
<p><strong>Selecionando tipos distintos em uma coluna</strong> Caso queira verificar quais são os tipos diferentes em determinada coluna você poderá utilizar o distinct para trazer apeanas os valores diferentes.</p>
<p>por exemplo: em uma determinada tabela chamada produto temos a coluna nome, e nessa coluna temos diversos valores diferentes mas queremos trazer apenas o valores distintos uns dos outros, então podemos fazer o comando:</p>
<pre><code class="lang-sql">    <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">distinct</span>(nome) <span class="hljs-keyword">from</span> produtos;
</code></pre>
<p>Como resultado será retornado todos os nomes de produtos que se tem valores diferentes.</p>
<p><strong>Seleção com Regexp</strong> Podemos utilizar expressões regulares para selecionar dados em uma tabela, alguns exemplos abaixo.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> nome <span class="hljs-keyword">from</span> testes.produtos <span class="hljs-keyword">where</span> nome regexp <span class="hljs-string">'^[cp]'</span>;
</code></pre>
<p>No exemplo acima, utilizamos o caractere especial <strong>^</strong> fora dos colchetes para dizer que qualquer <strong>nome</strong> que comece com a letra <strong>c</strong> ou <strong>p</strong> será retornado nessa consulta.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> nome <span class="hljs-keyword">from</span> testes.produtos <span class="hljs-keyword">where</span> nome regexp <span class="hljs-string">'^[^cp]'</span>;
</code></pre>
<p>Nesse outro exemplo fizemos o <strong>NOT</strong>, quando colocamos <strong>^</strong> dentro do colchete estamos trazendo uma negação para a consulta, nesse caso seria descrito: selecione nome de produtos desde que não comece com <strong>c</strong> ou <strong>p</strong></p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> nome <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">where</span> nome regexp <span class="hljs-string">'[a]$'</span>;
</code></pre>
<p>Com a utilização do caractere $ no final de uma expressão estamos dizendo que queremos selecionar todos os nomes que terminem com a, caso estivesse com o ^a seria um NOT.</p>
<p><strong>Seleção com group by</strong> A clausula group by tem por finalidade como o nome já diz retornar dados agrupados por, um exemplo seria: digamos que temos uma tabela de endereço e nessa tabela temos usuarios de varios estados e temos também vários usuários que moram no mesmo Estado, com essa cláusula fica facil saber quantos usuários tem em cada estado.</p>
<p>Na tabela endereco temos as colunas, estado, nome_usuario e endereco</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> estado, <span class="hljs-keyword">count</span>(estado) <span class="hljs-keyword">from</span> endereco <span class="hljs-keyword">group</span> <span class="hljs-keyword">by</span> estado;
</code></pre>
<p>Descrevendo o comando: selecione estado contando todos os estados e agrupando por estado, dessa forma como SP tem varias pessoas ele vai agrupar nessa linha o resultado para sp, se RJ tiver varios usuarios ele também vai agrupar esses usuarios em uma linha especifica.</p>
<p><strong>Having o where do group by</strong> Quando queremos filtros em cima de dados agrupados podemos utilizar a cláusula having.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> estado <span class="hljs-keyword">count</span>(estado) <span class="hljs-keyword">from</span> estado <span class="hljs-keyword">group</span> <span class="hljs-keyword">by</span> estado <span class="hljs-keyword">having</span> <span class="hljs-keyword">count</span>(estado)=<span class="hljs-number">1</span>;
</code></pre>
<p>dessa forma podemos construir filtros em cima do que foi agrupado em nossa consulta. ainda poderíamos ser mais específicos trazendo um where logo após o from estado por exemplo</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> estado <span class="hljs-keyword">count</span>(estado) <span class="hljs-keyword">from</span> estado <span class="hljs-keyword">where</span> nome=<span class="hljs-string">'sp'</span> <span class="hljs-keyword">or</span> nome=<span class="hljs-string">'rj'</span> <span class="hljs-keyword">group</span> <span class="hljs-keyword">by</span> estado <span class="hljs-keyword">having</span> <span class="hljs-keyword">count</span>(estado) &gt; <span class="hljs-number">10</span>;
</code></pre>
<p><strong>Inner join</strong></p>
<p>Um dos assuntos que as pessoas ficam mais confusas é a utilização de inner join, Para illustrar imagine que você tenha uma tabela chamada <strong>alunos</strong> e outra tabela chamada <strong>cursos</strong>, para saber quais cursos tem alunos e quais alunos estão presentes em cursos podemos utilizar o artifício do inner join.</p>
<p><img src="https://user-images.githubusercontent.com/5201283/107166756-b43ef300-6995-11eb-898b-2a64000eb775.png" alt="Screenshot from 2021-02-07 22-41-33" /></p>
<p>Na imagem acima podemos ver que a seleção a partir de <strong>inner join</strong> trará todas as intersecções entre alunos e cursos que está destacado com a seta vermelha, onde se vê as setas verdes são o <strong>outer join</strong> que em tradução literal é exterior, onde podemos perceber que ficando intuitivo, inner <strong>join para</strong> dados esperados <strong>outer join</strong> para dados exteriores.</p>
<p>Exemplo: digamos que nós temos uma tabela produtos e uma tabela categorias, onde cada produto pode estar com um relacionamento para uma categoria.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> p.nome, p.valor, c.nome, c.descricao
<span class="hljs-keyword">from</span> produtos p
<span class="hljs-keyword">inner</span> <span class="hljs-keyword">join</span> categorias c
<span class="hljs-keyword">on</span> p.categoria_id=c.id
</code></pre>
<p>No exemplo acima fizemos uma seleção de nome e valor da tabela produtos e nome e descrição de categorias, se tratando do inner join ele vai trazer todos os produtos que tem uma categoria inserida.</p>
<p>Observações, c e p são alias para suas respectivas tabelas.</p>
<p>Ainda falando do exemplo acima podemos fazer filtros nos resultados obtidos, por exemplo:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> p.nome, p.valor, c.nome, c.descricao
<span class="hljs-keyword">from</span> produtos p
<span class="hljs-keyword">inner</span> <span class="hljs-keyword">join</span> categorias c
<span class="hljs-keyword">on</span> p.categoria_id=c.id
<span class="hljs-keyword">where</span> c.nome=<span class="hljs-string">'comida'</span>
</code></pre>
<p>com filtros tão específicos fica fácil fazer seleções em tabelas relacionadas.</p>
<p><strong>left join</strong></p>
<p><img src="https://user-images.githubusercontent.com/5201283/107167328-64f9c200-6997-11eb-8746-bd3a308afb01.png" alt="Screenshot from 2021-02-07 22-53-57" /></p>
<p>Na imagem acima podemos ver o exemplo de um <strong>left join</strong>, no caso sendo selecionado o <strong>left join</strong> para <strong>alunos</strong> e <strong>cursos</strong> do lado <strong>right</strong>, o que será retornado nesse tipo de seleção é tudo do lado left e tudo do inner(meio ou intercecção), nada do right será retornado, imagine que na tabela estamos trazendo duas colunas <strong>nome_aluno</strong> e <strong>nome_curso</strong>, nesse caso ele vai trazer todos os alunos mesmo que não tenham nenhuma associação com algum curso alem de trazer todos os alunos que tenham.</p>
<p>exemplo de left join na tabela de produtos e categorias.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> p.nome, p.valor, c.nome, c.descricao
<span class="hljs-keyword">from</span> produtos
<span class="hljs-keyword">left</span> <span class="hljs-keyword">join</span> categorias c
<span class="hljs-keyword">on</span> p.id_categoria=c.id
</code></pre>
<p>com o left join podemos trazer todos os produtos que tenham e que não tenham uma categoria relacionada essa é a unica diferença entre o left e o inner</p>
<p><strong>Right join</strong></p>
<p><img src="https://user-images.githubusercontent.com/5201283/107167876-c3737000-6998-11eb-8d92-608cc1a4011e.png" alt="Screenshot from 2021-02-07 23-03-39" /></p>
<p>Na imagem acima podemos ver o exemplo de um <strong>right join</strong>, no caso sendo selecionado o <strong>right join</strong> para <strong>cursos</strong> e <strong>alunos</strong> do lado <strong>left</strong>, o que será retornado nesse tipo de seleção é tudo do lado right e tudo do inner(meio ou intercecção), nada do left será retornado, imagine que na tabela estamos trazendo duas colunas <strong>nome_aluno</strong> e <strong>nome_curso</strong>, nesse caso ele vai trazer todos os <strong>nome_curso</strong> mesmo que não tenham nenhuma associação com algum aluno especifico e apenas nome_aluno que tenha associação, alem de trazer todos os cursos que tenham.</p>
<p>exemplo de left join na tabela de produtos e categorias.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> p.nome, p.valor, c.nome, c.descricao
<span class="hljs-keyword">from</span> produtos
<span class="hljs-keyword">right</span> <span class="hljs-keyword">join</span> categorias c
<span class="hljs-keyword">on</span> p.id_categoria=c.id
</code></pre>
<p>Em determinada situação podemos querer saber apenas categorias que não tem nenhum produto setado, podemos fazer como abaixo</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> c.nome, c.descricao, p.nome, p.valor
<span class="hljs-keyword">from</span> categorias c
<span class="hljs-keyword">left</span> <span class="hljs-keyword">join</span> produtos p
<span class="hljs-keyword">on</span> c.id = p.id_categoria
<span class="hljs-keyword">where</span> p.nome <span class="hljs-keyword">is</span> <span class="hljs-literal">null</span>;
</code></pre>
<p>Selecione nome da categoria, descrição da categoria, nome do produto e valor do produto da tabela categoria, fazendo um left join com produtos, ou seja irá trazer categorias que tem produtos e categorias que não tem produtos, e por fim fazemos uma condição desde que o nome do produto seja null, nesse caso irá trazer apenas as categorais que não tem produtos cadastrados.</p>
<p>com o right join podemos trazer todos as categorias que tenham e que não tenham um produto relacionado essa é a unica diferença entre o right e o inner</p>
<p><strong>Remoção</strong></p>
<pre><code class="lang-sql"><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> tabela;
</code></pre>
<p>Comando para deletar uma tabela do banco de dados, <strong>um comando muito perigoso</strong>.</p>
<p>As vezes temos a necessidade de deletar apenas uma linha de nossa tabela então podemos executar o comando:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">from</span> table_teste <span class="hljs-keyword">where</span> <span class="hljs-keyword">id</span>=<span class="hljs-number">5</span>;
</code></pre>
<p>Atenção, sempre utilize o <strong>where</strong> esse é um comando muito perigoso, verifique se você tem um dump de backup de sua base de dados, e sempre se arrisque em ambiente de desenvolvimento <strong>nunca em produção</strong>.</p>
<p>**Comparações entre valores **</p>
<p>Se você tiver a necessidade de selecionar algum dado de uma tabela que esteja entre dois valores poderá utilizar a clausula <strong>between</strong>, essa cláusula não é apenas para comparativos entre datas, pode se utilzar outros valores para fazer os comparativos.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">Select</span> * <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">where</span>(data_inicio <span class="hljs-keyword">BETWEEN</span> <span class="hljs-string">'2020-12-16'</span> <span class="hljs-keyword">and</span> <span class="hljs-string">'2020-12-20'</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">status</span> = <span class="hljs-string">'1'</span>);
</code></pre>
<p>No exemplo acima filtramos um produto que está entre as datas <strong>16 do 12</strong> e <strong>20 do 12</strong> e que seu status esteja definido igual a <strong>1</strong></p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> nome <span class="hljs-keyword">as</span> Nome, preco <span class="hljs-keyword">as</span> Preço <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">as</span> p <span class="hljs-keyword">where</span>(p.preco <span class="hljs-keyword">between</span> <span class="hljs-number">10.00</span> <span class="hljs-keyword">and</span> <span class="hljs-number">15.00</span>);
</code></pre>
<p>Podemos trazer dois preços em algum intervalo de uma tabela, ou seja irá trazer preços que estejam entre 10 e 15 da tabela de produtos</p>
<p><strong>Atualização</strong></p>
<pre><code class="lang-sql"><span class="hljs-keyword">UPDATE</span> <span class="hljs-keyword">users</span> <span class="hljs-keyword">set</span> <span class="hljs-keyword">name</span>=<span class="hljs-string">'novo'</span>, idade=<span class="hljs-string">'23'</span> <span class="hljs-keyword">where</span>(<span class="hljs-keyword">id</span>=<span class="hljs-number">1</span>);
</code></pre>
<pre><code class="lang-sql"><span class="hljs-keyword">UPDATE</span> produtos <span class="hljs-keyword">set</span> nome=<span class="hljs-string">'maçã é muito boa'</span> <span class="hljs-keyword">where</span> <span class="hljs-keyword">id</span>=<span class="hljs-number">1</span>
</code></pre>
<p>Para atualizar uma tabela passamos a cláusula <strong>update</strong> seguida do nome da tabela e apos isso passamos o <strong>set</strong> para cada coluna que será atualizada, caso não passe alguma coluna ela permanecerá com o valor que já existe, e não custa lembrar para sempre passar a <strong>cláusula where</strong> para atualizar apenas a tabela selecionada.</p>
<p><strong>Adicionar campos a uma tabela</strong></p>
<p>Caso tenhamos a necessidade de adicionar campos em alguma tabela podemos fazer isso atravéz do alter table, veja o exemplo. <strong>ex1</strong></p>
<pre><code class="lang-sql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> produtos <span class="hljs-keyword">ADD</span> preco_de <span class="hljs-built_in">decimal</span>(<span class="hljs-number">10</span>,<span class="hljs-number">2</span>);
</code></pre>
<p>No exemplo acima passamos a cláusula <strong>alter table</strong> para alterar a tabela de produtos e passamos o <strong>add</strong> para adicionar um campo que nomeamos de <strong>preco_de</strong> passando seu tipo como <strong>decimal(10,2)</strong></p>
<p><strong>Removendo campo de uma tabelaex1</strong></p>
<pre><code class="lang-sql"><span class="hljs-keyword">alter</span> <span class="hljs-keyword">table</span> produtos <span class="hljs-keyword">drop</span> <span class="hljs-keyword">column</span> preco;
</code></pre>
<p>No exemplo acima nos alteramos a tabela produtos removendo a coluna preco.</p>
<p><strong>Explanação de recursos no mysql</strong></p>
<p>É possível verificar quanto de recurso uma consulta irá gastar, podemos fazer isso atravéz do explain</p>
<pre><code class="lang-sql"><span class="hljs-keyword">explain</span> <span class="hljs-keyword">select</span> * <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">where</span> nome=<span class="hljs-string">'maçã é boa'</span>;
</code></pre>
<p>com base nesse tipo de consulta podemos verificar quanto de recurso será utilizado</p>
<p><strong>Funções de agregação</strong></p>
<p>Podemos utilizar funções de agregação para fazer operações aritiméticas em uma determinada tabela, vamos ver alguns exemplos.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">from</span> produtos;
</code></pre>
<p>Conta todas as linhas de uma tabela</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(<span class="hljs-keyword">distinct</span> id_categoria) <span class="hljs-keyword">from</span> produtos;
</code></pre>
<p>Conta todas as linhas de uma tabela mas sem id_categoria repetidos, ou seja se tiver dois produtos que tem o mesmo id irá contar apenas o primeiro.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> <span class="hljs-keyword">max</span>(preco) <span class="hljs-keyword">from</span> produtos;
</code></pre>
<p>Seleciona o maior preço da tabela produto</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> <span class="hljs-keyword">min</span>(preco) <span class="hljs-keyword">from</span> produtos;
</code></pre>
<p>Seleciona o menor preço da tabela de produtos.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> <span class="hljs-keyword">min</span>(preco) <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">where</span> (<span class="hljs-keyword">id</span> &lt;= <span class="hljs-number">10</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">id</span> &gt;= <span class="hljs-number">5</span>);
</code></pre>
<p>Seleciona o menor preço da tabela de produtos desde que o id for menor ou igual a 10 e maior ou igual a 5</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> <span class="hljs-keyword">avg</span>(preco) <span class="hljs-keyword">from</span> produtos;
</code></pre>
<p>Podemos retornar a media de preços de todos os produtos ao qual passamos a função avg.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> <span class="hljs-keyword">sum</span>(preco) <span class="hljs-keyword">from</span> produtos;
<span class="hljs-keyword">select</span> <span class="hljs-keyword">sum</span>(preco) <span class="hljs-keyword">from</span> produtos <span class="hljs-keyword">where</span> (<span class="hljs-keyword">id</span>&gt;<span class="hljs-number">1</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">id</span> &lt;<span class="hljs-number">5</span>);
</code></pre>
<p>Somamos a coluna preço e trazemos a somatória de todos os preços, e no outro select somamos desde que o id for maior que 1 e menor que 5.</p>
<p><strong>Renomear uma tabela</strong></p>
<pre><code class="lang-sql"><span class="hljs-keyword">rename</span> <span class="hljs-keyword">table</span> table_teste <span class="hljs-keyword">to</span> test_new_name;
</code></pre>
<p>Com esse comando é possivel renomear uma tabela.</p>
<p><strong>Backup/restore de uma base de dados</strong> Para se fazer o backup de uma base de dados mysql você precisa do mysqldump que é um utilitário do mysql.</p>
<p>A partir do terminal você poderá seguir com o comando para executar os seu backup.</p>
<pre><code class="lang-plaintext">mysqldump -u root -p meu_banco &gt; /home/SEU_USER/dumps/meu_banco.sql
</code></pre>
<p>Para fazer a restauração de um banco de dados você pode utilizar o comando mysql</p>
<pre><code class="lang-plaintext">mysql -u root -p meu_novo_banco &lt; /home/andremartds/dumps/meu_banco.sql
</code></pre>
<p>Caso de uma restauração é necessário sempre observar que o novo banco de preferência esteja vazio, caso o banco não exista você pode utilizar comando abaixo.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">create</span> <span class="hljs-keyword">database</span> meu_novo_banco;
</code></pre>
<p><strong>Funcões</strong> Podemos utilizar funcões personalizadas no mysql, vamos colocar alguns exemplos:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">FUNCTION</span> fn_teste(n <span class="hljs-built_in">DECIMAL</span>(<span class="hljs-number">10</span>,<span class="hljs-number">2</span>), m <span class="hljs-built_in">int</span>)
<span class="hljs-keyword">returns</span> <span class="hljs-built_in">INT</span> <span class="hljs-keyword">deterministic</span>
<span class="hljs-keyword">return</span> n * m;
</code></pre>
<p>a função acima é muito simples, ela apenas multiplica um decimal com um inteiro e retorna um inteiro, quando executamos essa função ela será armazenada em nosso banco, podemos utilizar nossa função da seguinte forma.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> fn_teste (<span class="hljs-number">10.5</span>,<span class="hljs-number">20</span>) <span class="hljs-keyword">as</span> soma;
</code></pre>
<p><strong>Funcões com delimitadores</strong></p>
<pre><code class="lang-sql">DELIMITER $$
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">FUNCTION</span> adiciona_valor(preco <span class="hljs-built_in">DECIMAL</span>(<span class="hljs-number">10</span>,<span class="hljs-number">2</span>), aumento <span class="hljs-built_in">decimal</span>(<span class="hljs-number">10</span>,<span class="hljs-number">2</span>)) <span class="hljs-keyword">returns</span> <span class="hljs-built_in">decimal</span>(<span class="hljs-number">10</span>,<span class="hljs-number">2</span>) <span class="hljs-keyword">deterministic</span>
<span class="hljs-keyword">BEGIN</span>
    <span class="hljs-keyword">RETURN</span> preco + preco * aumento / <span class="hljs-number">100</span>;
<span class="hljs-keyword">END</span>$$
DELIMITER ;

<span class="hljs-keyword">select</span> <span class="hljs-keyword">concat</span>(<span class="hljs-string">'O total a pagar é = '</span>, adiciona_valor(<span class="hljs-number">100</span>, <span class="hljs-number">10</span>), <span class="hljs-string">' reais'</span>) <span class="hljs-keyword">as</span> valor;
</code></pre>
<p>A funcao acima adiciona uma porcentagem a um valor passado, mas o interessante desse exemplo são os delimitadores e o begin e end, dentro do bloco begin e and podemos ter nossas execuções e dessa forma podemos tratar valores para respostas, o problema é que por padrão o ponto e virgula sempre mata a execução e para resolver essa questão definimos outro delimitador, que pode ser qualquer caractére não reservado do myql.</p>
<p>após executamos a função ela será armazenada em nossa base de dados, e dai pomos executar, nesse caso concatenamos para uma melhor saída para o usuário.</p>
<p><strong>Procedimentos armazenados</strong></p>
<p>No myslq podemos criar procedimentos armazenados, Logo abaixo podemos ver um procedimento que tem por nome verPreco e como parâmetro passamos o id de um produto sendo do tipo int, o selecionamos e concatenamos com uma mensagem para trazer uma mensagem, id e valor com um alias, logo depois definimos a tabela que vamos selecionar e também a partir de que condição(where), nesse caso estamos trazendo pelo id do produto que foi o que passamos por parâmetros.</p>
<pre><code class="lang-sql"><span class="hljs-comment"># criação</span>
<span class="hljs-keyword">create</span> <span class="hljs-keyword">procedure</span> verPreco(id_produto <span class="hljs-built_in">int</span>)
<span class="hljs-keyword">select</span> <span class="hljs-keyword">concat</span>(<span class="hljs-string">'o preço é do produto identificado pelo id '</span>,p.id, p.valor) <span class="hljs-keyword">as</span> <span class="hljs-string">'Descrição'</span>
<span class="hljs-keyword">from</span> produtos p
<span class="hljs-keyword">where</span> p.id = id_produto;

<span class="hljs-comment"># vamos chamar nosso procedimento</span>
<span class="hljs-keyword">call</span> verPreco(<span class="hljs-number">1</span>);
</code></pre>
<p>Obrigado por chegar até aqui!! um abraço!! ;)</p>
]]></content:encoded></item></channel></rss>