quinta-feira, 8 de fevereiro de 2024

Relacionamento bidirecional recursivo com JPA

           Neste artigo vou mostrar um exemplo de um relacionamento bidirecional recursivo, ou seja, o objeto faz referência a ele mesmo. 


As vezes ao invés de usar herança, essa solução resolve de forma mais simples não tendo que alterar muita coisa no modelo já existente. Recentemente usei ela para o desdobramento de uma entidade que era a base do sistema e foi reclassificado em elementos "pai e filho". 


Claro que houve a necessidade de aumentar alguns campos na tabela que serão usados apenas quando for "filho" ou "pai", mas a desnormalização do modelo muitas vezes se faz necessário. O uso de outra solução acarretaria em uma grande mudança em todo o sistema. 


Para o exemplo vamos pensar para fins didáticos em uma cadeia de comando onde um Chefe tem Subordinados, mas também está subordinado à um Chefe.

 

No banco existem os seguintes campos: id, nome e chefe_superior_id. Segue o código:

 

 

import javax.persistence.*;

import java.util.List;

 

@Entity

@Table(name = "chefe")

public class Chefe {

 

    @Id

    @GeneratedValue(strategy = GenerationType.IDENTITY)

    private Long id;

 

    @Column(name = "nome")

    private String nome;

 

  @OneToMany(mappedBy = "chefe", cascade = CascadeType.ALL, fetch = FetchType.LAZY)

    private List<Chefe> subordinados;

 

    @ManyToOne

    @JoinColumn(name = "chefe_superior_id")

    private Chefe chefe;

 

    // getters e setters

 

}

segunda-feira, 18 de dezembro de 2023

Aumentando o limite do tamanho de upload de arquivos do JBoss EAP

 

Nesse artigo vou mostrar como permitir requisições de grande tamanho para o JBoss EAP. Por padrão ele barra requisições maiores que 10Mb, o que para os dias atuais não é muita coisa, já que qualquer imagem ou PDF facilmente passa esse tamanho.

 

No JBoss EAP, a partir da versão 7 foi incluído um novo servidor web extremamente leve e de alto desempenho da própria RedHat chamado Undertown, substituindo o Tomcat que rodava internamente no JBoss. No standalone.xml encontramos seu submódulo como abaixo:

 

<subsystem xmlns="urn:jboss:domain:undertow:4.0">

<buffer-cache name="default"/>

     <server name="default-server">

<http-listener name="default" socket-binding="http" enable-http2="false"/>

<ajp-listener name="ajp" socket-binding="ajp" />

<host name="default-host" alias="localhost">

               <location name="/" handler="welcome-content"/>

               <filter-ref name="server-header"/>

               <filter-ref name="x-powered-by-header"/>

</host>

</server>

     <servlet-container name="default">

          <jsp-config/>

          <websockets/>

     </servlet-container>

     <handlers>

<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>

</handlers>

<filters>

<response-header name="server-header" header-name="Server" header-value="JBoss-EAP/7"/>

          <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>

    </filters>

</subsystem>

 

 

E é nele que precisamos configurar a permissão para grandes arquivos, dentro das tags <http-listener> e <ajp-listener>. Nesse exemplo vou configurar para 1GB, mas você precisa ver de acordo com sua necessidade.

 

<subsystem xmlns="urn:jboss:domain:undertow:4.0">

<buffer-cache name="default"/>

     <server name="default-server">

<http-listener name="default" socket-binding="http" max-post-size="1073741824" enable-http2="false"/>

<ajp-listener name="ajp" socket-binding="ajp" max-post-size="1073741824" />

<host name="default-host" alias="localhost">

               <location name="/" handler="welcome-content"/>

               <filter-ref name="server-header"/>

               <filter-ref name="x-powered-by-header"/>

</host>

</server>

     <servlet-container name="default">

          <jsp-config/>

          <websockets/>

     </servlet-container>

     <handlers>

<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>

</handlers>

<filters>

<response-header name="server-header" header-name="Server" header-value="JBoss-EAP/7"/>

          <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>

    </filters>

</subsystem>

 

 

Com isso o JBoss agora passa a permitir um grande tráfego de dados, mas ainda é possível configurar outros controles como no Spring por exemplo.

quarta-feira, 1 de novembro de 2023

Functions, Triggers e Procedures no PostgreSQL

   

       Nesse artigo vou trazer um exemplo de Functions, Triggers e Procedures no PostgreSQL. Antes vamos entender um pouco a diferença entre eles:

         

1.   Funções (Functions):

·         As funções são rotinas ou subprogramas que recebem um ou mais parâmetros de entrada, realizam cálculos ou operações e retornam um valor.

·         Elas podem ser chamadas a partir de instruções SQL, expressões ou outras funções.

·         As funções podem ser usadas para encapsular lógica de negócio complexa e fornecer um resultado computado.

·         Exemplo: Uma função que calcula a idade com base na data de nascimento.

2.   Triggers:

·         Triggers são procedimentos armazenados que são automaticamente invocados em resposta a um evento específico que ocorre no banco de dados.

·         Eles são acionados por ações, como inserção, atualização ou exclusão de dados em uma tabela.

·         Os triggers podem ser usados para impor regras de negócio, manter integridade referencial, auditar alterações de dados, entre outras funcionalidades.

·         Exemplo: Um trigger que atualiza um campo de data de modificação sempre que uma linha é atualizada em uma tabela.

3.   Procedimentos (Procedures):

·         Os procedimentos são rotinas ou subprogramas que podem receber parâmetros de entrada, executar um conjunto de instruções e, opcionalmente, retornar valores.

·         Eles são usados para agrupar um conjunto de instruções que podem ser executadas repetidamente ou como uma unidade lógica.

·         Os procedimentos podem ser chamados a partir de outros procedimentos, instruções SQL ou de uma aplicação externa.

·         Exemplo: Um procedimento que insere um registro em uma tabela e atualiza um contador.

 

Agora vamos aos exemplos:

 

1 – Function

 

-- Função

CREATE OR REPLACE FUNCTION calcularIdade(data_nascimento DATE) RETURNS INTEGER AS

DECLARE

  idade INTEGER;

BEGIN

  idade := EXTRACT(YEAR FROM CURRENT_DATE) - EXTRACT(YEAR FROM data_nascimento);

  RETURN idade;

END;

LANGUAGE plpgsql;

 

--Chamada da função

SELECT calcularIdade('1990-05-10');

 

2 – Trigger

 

-- Temos uma tabela

CREATE TABLE produtos (

  id SERIAL PRIMARY KEY,

  nome VARCHAR(50),

  quantidade INTEGER,

  data_atualizacao DATE

);

 

-- Criação da função usada pelo Trigger

CREATE OR REPLACE FUNCTION atualizarDataAtualizacao()

  RETURNS TRIGGER AS

DECLARE

BEGIN

  NEW.data_atualizacao := CURRENT_DATE;

  RETURN NEW;

END;

LANGUAGE plpgsql;

 

-- Criação da Trigger

CREATE TRIGGER trigger_atualizar_data

  BEFORE INSERT OR UPDATE ON produtos

  FOR EACH ROW

  EXECUTE FUNCTION atualizarDataAtualizacao();

 

-- Utilização da Trigger ocorre automaticamente

INSERT INTO produtos (nome, quantidade) VALUES ('Produto A', 10);

UPDATE produtos SET quantidade = 20 WHERE id = 1; 

 

Note nesse trecho de código, na criação da função da trigger, o uso da palavra NEW. NEW é uma referência a uma variável especial em PL/pgSQL usada em gatilhos (triggers) no PostgreSQL. Quando um gatilho é acionado, ele tem acesso a duas variáveis especiais: OLD e NEW.

 

OLD contém os valores anteriores das colunas afetadas pela ação que disparou o gatilho.

NEW contém os novos valores que serão inseridos ou já foram inseridos devido à ação que disparou o gatilho.

 

No trecho de código acima, NEW.data_atualizacao está sendo usado para atribuir a data atual à coluna data_atualizacao da linha que está sendo inserida ou atualizada.

 

3 – Procedure

-- Criação da Procedure

CREATE OR REPLACE PROCEDURE inserirProduto(nome VARCHAR(50), quantidade INTEGER)

  AS

DECLARE

BEGIN

  INSERT INTO produtos (nome, quantidade, data_atualizacao)

  VALUES (nome, quantidade, CURRENT_DATE);

END;

LANGUAGE plpgsql;

 

-- Utilização da Procedure

CALL inserirProduto('Produto B', 15);

Programação funcional no Java (Java 8+)

      Nesse artigo vou falar um pouco sobre programação funcional no Java. A programação funcional se refere ao uso de conceitos e técnicas como funções de ordem superior, expressões lambda, programação sem efeitos colaterais, imutabilidade e streams, para escrever código mais conciso, legível (nem sempre) e robusto. Esses recursos estão disponíveis a partir do Java 8.

 

Aqui estão alguns conceitos chave relacionados à programação funcional no Java:

 

1. Expressões Lambda: As expressões lambda permitem definir funções anônimas (funções sem nome) de forma concisa. Elas são usadas em várias partes do código, como argumentos para métodos, implementações de interfaces funcionais e para criar objetos ‘Comparator’. É sempre bom lembrar da importância da legibilidade do código, porque nem todos tem a mesma experiência, e o uso exagerado pode atrapalhar. Um exemplo de função lambda:

 

  (a, b) -> a + b  // Uma expressão lambda que adiciona dois números

 

2. Interfaces Funcionais: As interfaces funcionais são interfaces que têm um único método abstrato. Alguns exemplos incluem ‘Function’, ‘Predicate’, ‘Consumer’ e ‘Supplier’. Você pode usar expressões lambda para implementar essas interfaces de maneira concisa.

 

3. Streams: Os Stream’s são sequências de elementos que podem ser processadas de forma funcional. Eles permitem realizar operações de consulta, transformação e agregação em coleções de dados, como listas e conjuntos. Os Stream’s operam de forma lazy e podem ser processados sequencialmente ou em paralelo.

 

4. Imutabilidade: A programação funcional incentiva a imutabilidade, o que significa que objetos não devem ser alterados após a criação. Em vez disso, você cria novos objetos com base em objetos existentes. Isso evita efeitos colaterais e torna o código mais previsível.

 

5. Funções de Ordem Superior: Funções de ordem superior são funções que podem receber outras funções como argumentos e/ou retornar funções como resultado. No Java, usando programação funcional, você pode passar funções como argumentos para métodos e implementar métodos que aceitam funções como parâmetros.

 

6. Recursão Funcional: A programação funcional incentiva o uso de recursão funcional, onde os métodos se chamam de forma recursiva, evitando loops tradicionais. Isso promove um código mais declarativo. Porém tem que se tomar muito cuidado, pois o Java faz uso da pilha de chamadas, e caso essas chamadas recursivas sejam muito longas pode quebrar. Embora esteja disponível, é uma boa prática dar preferência  aos loops tradicionais caso o número de chamadas seja desconhecido ou sabidamente grande.

 

Aqui está um exemplo de programação funcional usando uma expressão lambda e um Stream:

 

List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5);

 

//  calcular a soma dos quadrados dos números pares

int somaDosQuadradosDosPares = numeros.stream()

    .filter(n -> n % 2 == 0)  // Filtrar números pares

    .map(n -> n * n)  // Elevar ao quadrado

    .reduce(0, Integer::sum);  // Somar os resultados

 

System.out.println(somaDosQuadradosDosPares);  // Saída: 20

 

        A função ‘filter’ filtra os números pares, a função ‘map’ eleva ao quadrado (ambas usando expressão lambda) e ‘reduce’ soma os resultados. Isso ilustra a programação funcional em Java, tornando o código mais enxuto, embora nem sempre mais claro. 

Transformando String de Inteiros em Lista usando Programação Funcional

             Nesse artigo vou mostrar como transformar uma String de números inteiros separadas por “;” em um Array de Integer usando programação funcional em Java.

         

       A programação funcional ajuda muito a reduzir códigos, embora possa também, dependendo da forma que utilizada, perder um pouco legibilidade dele. Então as vezes usar uma forma não tão reduzida das funções e colocar comentários ajuda bastante. Lembre-se que nem todo mundo que programa tem o mesmo nível de experiência.

 

          O código abaixo monta um Stream (Um Stream é uma sequência de elementos que pode ser processada de forma sequencial ou paralela) a partir do split da String, usando o Map para transformar os dados (ele pode ser usado para converter tipos de dados, para chamar funções como UpperCase, etc.) e depois retornados como uma lista.

 

import java.util.Arrays;

import java.util.List;

import java.util.stream.Collectors;

 

public class Exemplo {

    public static void main(String[] args) {

 

        String str = "10;20;30;40;50";

  

        List<Integer> integerList = Arrays.stream(str.split(";"))

                .map(Integer::parseInt)

                .collect(Collectors.toList());

       

        integerList.forEach(System.out::println);

    }

}

quarta-feira, 26 de julho de 2023

Trabalhando com Arquivos (File) e Array de Bytes no Java

     As vezes precisamos transformar um arquivo em array de bytes e visse e versa seja para guardar o arquivo em banco ou tranferir na rede, e aqui seguem duas funções para fazer esse De-Para:


        public byte[] convertFileToByte(File file){
FileInputStream fileInputStream=null;
byte[] bFile = new byte[(int) file.length()];
try {
    //convert file into array of bytes
fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
   
}catch(Exception e){
e.printStackTrace();
}
return bFile;
}

public File convertByteToFile(byte[] bYtes){
File file = new File("file");
BufferedOutputStream bos;
try {
bos = new BufferedOutputStream(new FileOutputStream(file));
bos.write(bYtes); 
bos.close(); 
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();

return file;
}

quarta-feira, 19 de julho de 2023

Aplicando Máscara CNPJ em um campo no SQL Server

 

Muitas vezes os campos como CNPJ e CPF são guardados no banco de dados sem a formatação e pode acontecer de precisarmos pegar eles já formatados.

 

Bom, segue abaixo um exemplo de função que formata no padrão CNPJ, e que também serve de base para formatar um CPF.

 

DECLARE @cnpj CHAR(14) = '3477929600012'; -- Insira o CNPJ aqui

 

SELECT

STUFF(STUFF(STUFF(STUFF(

RIGHT('00000000000000' + @cnpj, 14), -- Completa com zeros à esquerda

3, 0, '.'), 7, 0, '.'), 11, 0, '/'), 16, 0, '-') AS CNPJformatado;

 

Primeiro são acrescentados 14 zeros a esquerda e então a função RIGHT é usada para pegar os últimos 14 dígitos do CNPJ, sendo assim, não importa quantos números faltem, eles serão preenchidos com zeros.

 

A função STUFF é aplicada em posições específicas para inserir os pontos, a barra e o traço usados na formatação do CNPJ.

 

Pra este artigo é só, espero que ajude.