mardi 21 février 2023

6 Méthodes utiles pour manipuler des chaînes de caractères en Java


Méthodes utiles pour les chaînes de caractères en Java

Les chaînes de caractères sont très courantes en Java, et il existe plusieurs méthodes utiles pour les manipuler.

Voici quelques-unes de ces méthodes, accompagnées d'exemples de code Java.

  1. strip()

La méthode strip() est une méthode ajoutée à Java 11 qui est similaire à la méthode trim(), mais qui prend en charge les nouveaux caractères Unicode tels que les espaces insécables. Voici un exemple de code qui utilise la méthode strip() :

java
String str = " Hello, World! ";
String stripped = str.strip();
System.out.println(stripped);

Le résultat de ce code sera "Hello, World!".

  1. isBlank()

La méthode isBlank() est également ajoutée à Java 11, et elle permet de vérifier si une chaîne de caractères est vide ou ne contient que des espaces. Cette méthode est différente de la méthode isEmpty() qui vérifie si la chaîne est vide en vérifiant si sa longueur est égale à zéro. Voici un exemple de code qui utilise la méthode isBlank() :

java
String str = " ";
boolean isBlank = str.isBlank();
System.out.println(isBlank);

Le résultat de ce code sera "true".

  1. Boucler sur une chaîne de caractères

Pour boucler sur une chaîne de caractères, vous pouvez utiliser la méthode toCharArray(), qui retourne un tableau de caractères, et parcourir le tableau avec une boucle for. Vous pouvez également utiliser la méthode charAt(i) pour accéder à chaque caractère individuellement. Voici un exemple de code qui utilise une boucle for pour boucler sur une chaîne de caractères :

java
String str = "Hello, World!";
char[] charArray = str.toCharArray();
for (char c : charArray) { System.out.println(c); }

Le résultat de ce code sera l'affichage de chaque caractère de la chaîne sur une ligne séparée.

  1. StringBuilder pour la concaténation

Si vous devez concaténer des chaînes de caractères en Java, vous pouvez utiliser la classe StringBuilder plutôt que la concaténation de chaînes de caractères avec l'opérateur +. La classe StringBuilder est plus efficace en termes de mémoire, car elle crée une seule instance mutable de la chaîne de caractères. Voici un exemple de code qui utilise StringBuilder pour concaténer des chaînes de caractères :

java
String str1 = "Hello,";
  String str2 = " World!";
StringBuilder sb = new StringBuilder();
sb.append(str1);
sb.append(str2);
String result = sb.toString();
System.out.println(result);

Le résultat de ce code sera "Hello, World!".

  1. transform()

La méthode transform() est une méthode ajoutée à Java 12, qui permet de transformer une chaîne de caractères à l'aide d'une fonction. Voici un exemple de code qui utilise la méthode transform() :

java
String str = "hello, world!"; String transformed = str.transform(s -> s.toUpperCase()); System.out.println(transformed);

Le résultat de ce code sera "HELLO, WORLD!".


  1. Vérifier si une chaîne contient des caractères ou des nombres. Il y a plusieurs façons de vérifier si une chaîne de caractères contient des caractères ou des nombres. Voici trois approches courantes:
    1. Convertir la chaîne en un tableau de caractères et vérifier chaque caractère à l'aide de la méthode Character.isDigit(). Cette méthode renvoie true si le caractère est un chiffre et false sinon. Par exemple:
  2. java
    String str = "abc123";
    char[] chars = str.toCharArray();                 
    boolean containsDigit = false;
    for (char c : chars) {
    if (Character.isDigit(c)) {
     containsDigit = true; break; }
    }
    System.out.println("La chaîne " + str + " contient un chiffre: " + containsDigit);
    1. Utiliser la méthode String.chars() pour créer un flux de caractères et vérifier si tous les caractères sont des chiffres à l'aide de la méthode Character.isDigit(). Cette méthode renvoie true si tous les caractères sont des chiffres et false sinon. Par exemple:
    java
    String str = "abc123";
    boolean allDigits = str.chars().allMatch(Character::isDigit); System.out.println("La chaîne " + str + " ne contient que des chiffres: " + allDigits);
    1. Utiliser une expression régulière pour vérifier si la chaîne ne contient que des chiffres. Par exemple:
    java
    String str = "abc123";
    boolean allDigits = str.matches("[0-9]+");
    System.out.println("La chaîne " + str + " ne contient que des chiffres: " + allDigits);

    Notez que cette méthode ne vérifie que si la chaîne ne contient que des chiffres. Si vous voulez vérifier si la chaîne contient des lettres et des chiffres, vous devrez utiliser une expression régulière différente.

    Enfin, pour une vérification plus souple, vous pouvez utiliser un prédicat comme deuxième paramètre. Par exemple:

    java
    String str = "abc123";
    boolean containsLetterOrDigit =str.chars().anyMatch(Character::isLetterOrDigit);
    System.out.println("La chaîne " + str + " contient une lettre ou un chiffre: " + containsLetterOrDigit);

    Cela vérifiera si la chaîne contient soit une lettre, soit un chiffre.



Les architectures de Kafka et RabbitMQ : des choix distincts pour les traitements de flux de données en temps réel et la messagerie de type file d'attente

 Kafka et RabbitMQ sont tous deux des brokers de messages populaires utilisés pour la communication entre applications distribuées. Cependant, il y a des différences clés entre les deux.


L'une des principales différences entre Kafka et RabbitMQ est leur architecture respective.

Kafka est conçu pour être un système de traitement de flux de données (streaming) distribué, ce qui signifie qu'il est optimisé pour la gestion de gros volumes de données en temps réel. Kafka utilise un modèle de publication/abonnement (pub/sub) pour la diffusion des messages, où les messages sont stockés dans des partitions de journal (log partitions) qui sont répliquées sur plusieurs nœuds.

En revanche, RabbitMQ est un système de messagerie de type file d'attente qui utilise un modèle de messagerie basé sur les files d'attente (queues). RabbitMQ stocke les messages dans des files d'attente qui sont réparties entre les nœuds de la file d'attente (queue nodes).

Une autre différence importante est que Kafka a une rétention de données intégrée, ce qui signifie que les messages sont conservés pendant une période de temps spécifiée, même après que les consommateurs les aient traités. Cela permet de retraiter les données si nécessaire. En revanche, RabbitMQ n'a pas de rétention de messages intégrée. Par défaut, RabbitMQ supprime les messages de la file d'attente une fois qu'ils ont été consommés par les abonnés.

Cependant, il est important de noter que RabbitMQ peut être configuré pour stocker les messages de manière persistante, en les stockant dans des files d'attente durables sur le disque. Cela permet de garantir que les messages ne sont pas perdus en cas de défaillance du nœud de la file d'attente. De plus, RabbitMQ permet de configurer des stratégies de reprise (retry) pour les messages qui n'ont pas pu être consommés, ce qui peut être utile dans les cas où la consommation de messages échoue pour des raisons temporaires.


Kafka n'a pas de mécanisme de routage pour les messages. RabbitMQ dispose d'un mécanisme de routage utilisant un exchange, qui achemine le message vers une ou plusieurs files d'attente. RabbitMQ peut acheminer le message en fonction de la clé de routage. Plusieurs échanges sont disponibles : fanout, direct et topic. Chacun a des fonctionnalités différentes. L'éditeur peut attacher une clé de routage et RabbitMQ acheminera le message vers une ou plusieurs files d'attente à consommer.

Voici un tableau qui résume les principales différences d'architecture entre Kafka et RabbitMQ :

KafkaRabbitMQ
Type de systèmeSystème de traitement de flux de données en temps réelSystème de messagerie de type file d'attente
Modèle de publication/abonnementOui (Pull Model )Non (basé sur les files d'attente) (Push Model des messages vers les consommateur)
Modèle de messageriePartition de journal (log partition)File d'attente (queue)
RéplicationRéplication des partitions de journal sur plusieurs nœudsRéplication des files d'attente sur plusieurs nœuds
Rétention de donnéesIntégrée Les messages sont stockés sur le disque pendant une période de temps définie par la politique de rétention Non intégrée (Les messages sont stockés en mémoire ou sur le disque jusqu'à ce qu'un consommateur les acquitte)
Gestion des consommateursLes consommateurs contrôlent leur propre avancementLe broker contrôle l'avancement des messages pour les consommateurs
Coût d'exploitationLes coûts d'exploitation de Kafka sont plus élevés que ceux de RabbitMQ, car Kafka nécessite des serveurs plus puissants pour supporter un grand volume de données.Les coûts d'exploitation de RabbitMQ sont généralement moins élevés que ceux de Kafka, car RabbitMQ peut être exécuté sur des serveurs moins puissants et nécessite moins de ressources pour supporter un grand volume de données.
Cas d'utilisationStreaming de données, data pipeline, logs distribuésSéries de tâches, communication inter-service, traitement de tâches asynchrones

En résumé, Kafka est conçu pour le traitement de flux de données en temps réel, avec un modèle de publication/abonnement et une rétention de données intégrée, tandis que RabbitMQ est un système de messagerie de type file d'attente, avec un modèle de messagerie basé sur les files d'attente et la possibilité de stocker les messages de manière persistante. Les deux systèmes offrent un débit élevé de messages, mais Kafka est optimisé pour une latence faible, tandis que RabbitMQ a une latence plus élevée en raison de son modèle de messagerie basé sur les files d'attente. Pour plus de profondeur, très bien détaillé : https://jack-vanlightly.com/blog/2017/12/3/rabbitmq-vs-kafka-series-introduction https://aws.amazon.com/fr/compare/the-difference-between-rabbitmq-and-kafka/

lundi 30 mai 2022

Spring Initialize a Database Using Hibernate datasource configuration

I can't believe this the default mode configuration with hibernate, in our test everytime hibernate is dropping the table  and recreating it on every execution of Spring, so we lost the data. 

If an embedded database is identified and no schema manager (Flyway or Liquibase) has been detected, ddl-auto defaults to create-drop

refere to : https://docs.spring.io/spring-boot/how-to/data-initialization.html

How to tell to Spring Don't do that, please :) ?

jpa:
hibernate:
ddl-auto:update # don't remove anything


In production, spring.jpa.hibernate.ddl-auto should be disabled (not specified) or set to validate, and the database migration should be managed via dedicated tools such as Flyway or Liquibase


jpa:
hibernate:
ddl-auto:none

This allow our schema file to create the repository, instead to allowing hibernate to do it.

But for setting h2 for test 

spring.jpa.hibernate.ddl-auto property is not explicitly configured, Spring Boot uses create-drop for embedded databases such as H2 by default

Note: It is strongly recommended to set the spring.jpa.hibernate.ddl-auto property to none in a production environment—this prevents Spring Data JPA to manipulate the structure of the SQL tables.

jpa:
hibernate:
ddl-auto: create-drop

 spring:

  # [ Base fichier H2 ]
datasource:
platform: h2
url: jdbc:h2:./test-h2/test-db;DB_CLOSE_DELAY=-1;MODE=Oracle;TRACE_LEVEL_FILE=4;AUTO_SERVER=TRUE
driver-class-name: org.h2.Driver
username: sa
password:
h2:
console:
path: /manage/h2/console
enabled: true
jpa:
hibernate:
ddl-auto: create-drop
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect

samedi 1 janvier 2022

[SQL] SQL Query Order of Execution

Introduction :

L’ordre d’exécution des requêtes SQL est un concept essentiel pour comprendre comment écrire des requêtes sans erreur qui s’exécutent efficacement.

Problème :

Lors de l’écriture de requêtes SQL, nous écrivons généralement les clauses dans cet ordre : SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, puis LIMIT. Cependant, l’ordre dans lequel la base de données interprète la requête est légèrement différent. Cette différence peut entraîner des erreurs ou une inefficacité lors de l’exécution des requêtes.

Voici quelques exemples de mauvaises pratiques liées à l’ordre des opérations SQL qui peuvent ne pas donner le résultat attendu :

  1. Utilisation de HAVING avant GROUP BY : La clause HAVING est utilisée pour filtrer les résultats après l’agrégation des données avec GROUP BY. Si vous utilisez HAVING avant GROUP BY, vous obtiendrez une erreur car HAVING ne peut pas fonctionner sur des données non agrégées. Par exemple :

    SELECT COUNT(*), department
    FROM employees
    HAVING COUNT(*) > 5
    GROUP BY department;
    

    Cette requête générera une erreur car HAVING est utilisé avant GROUP BY.

  2. Utilisation de alias de colonne dans WHERE : Les alias de colonne définis dans SELECT ne sont pas accessibles dans WHERE, car WHERE est exécuté avant SELECT. Par exemple :

    SELECT salary * 0.9 AS adjusted_salary
    FROM employees
    WHERE adjusted_salary > 50000;
    

    Cette requête générera une erreur car adjusted_salary n’est pas accessible dans WHERE.

  3. Utilisation de LIMIT dans une sous-requête : En SQL standard, LIMIT n’est pas autorisé dans les sous-requêtes. Par exemple :

    SELECT employee_id, salary
    FROM (
        SELECT employee_id, salary
        FROM employees
        ORDER BY salary DESC
        LIMIT 10
    ) AS top_employees;
    

    Cette requête peut générer une erreur dans certains systèmes de gestion de bases de données qui suivent strictement le standard SQL.

Ces exemples illustrent l’importance de comprendre l’ordre d’exécution des opérations SQL pour éviter les erreurs et obtenir les résultats attendus.

Solution :  

Pour résoudre ce problème, il est important de comprendre l’ordre d’exécution réel des requêtes SQL:

  1. FROM : La première partie de la requête que la base de données lira est la clause FROM. Ce sont les tables dont nous extrayons les données.
  2. WHERE : La clause WHERE est l’endroit où nous filtrons les lignes de la table.
  3. GROUP BY : La clause GROUP BY est souvent utilisée en conjonction avec des fonctions d’agrégation pour renvoyer une agrégation de résultats regroupés par une ou plusieurs colonnes.
  4. HAVING : La clause HAVING nous permet de filtrer un ensemble de résultats après que les données ont été regroupées et agrégées.
  5. SELECT : L’instruction SELECT est l’endroit où nous définissons les colonnes et les fonctions d’agrégation que nous voulons renvoyer en tant que colonnes sur notre table.
  6. DISTINCT : DISTINCT vient plus tard dans l’ordre des opérations, car il supprime les lignes en double après que toutes les lignes ont été sélectionnées.
  7. UNION : Une union prend deux requêtes qui peuvent toutes deux se tenir seules en tant que requêtes valides et les empile l’une sur l’autre pour se combiner en une seule.

corrections :

  1. Mauvaise pratique : Utilisation de HAVING avant GROUP BY

    SELECT COUNT(*), department
    FROM employees
    HAVING COUNT(*) > 5
    GROUP BY department;
    

    Correction : Utilisez HAVING après GROUP BY.

    SELECT COUNT(*), department
    FROM employees
    GROUP BY department
    HAVING COUNT(*) > 5;
    
  2. Mauvaise pratique : Utilisation de alias de colonne dans WHERE

    SELECT salary * 0.9 AS adjusted_salary
    FROM employees
    WHERE adjusted_salary > 50000;
    

    Correction : Utilisez l’alias de colonne dans HAVING ou déplacez le calcul dans WHERE.

    SELECT salary * 0.9 AS adjusted_salary
    FROM employees
    HAVING adjusted_salary > 50000;
    
    -- ou
    
    SELECT salary * 0.9 AS adjusted_salary
    FROM employees
    WHERE salary * 0.9 > 50000;
    
  3. Mauvaise pratique : Utilisation de LIMIT dans une sous-requête

    SELECT employee_id, salary
    FROM (
        SELECT employee_id, salary
        FROM employees
        ORDER BY salary DESC
        LIMIT 10
    ) AS top_employees;
    

    Correction : Utilisez LIMIT dans la requête principale.

    SELECT employee_id, salary
    FROM employees
    ORDER BY salary DESC
    LIMIT 10;
    

Discussion 

Comprendre cet ordre d’exécution peut vous aider à diagnostiquer pourquoi une requête ne s’exécute pas et vous aidera à optimiser vos requêtes pour qu’elles s’exécutent plus rapidement

Par exemple, parce que la clause FROM vient avant la clause WHERE, vous pouvez filtrer les résultats avec une CTE avant de les joindre dans votre requête finale pour optimiser votre requête.

https://www.sisense.com/blog/sql-query-order-of-operations/

mercredi 29 décembre 2021

[SQL] How to hanlde NULL values in the SELECT statement and convert them to 0?

Introduction

SQL est un langage de programmation de base de données largement utilisé pour stocker, interroger et manipuler des données. Cependant, lors de l’utilisation de SQL, les utilisateurs peuvent rencontrer un problème courant : la présence de valeurs NULL dans les colonnes des bases de données.

Problème

Une valeur NULL est une valeur inconnue ou indéfinie qui peut être présente dans une colonne de base de données. Ces valeurs NULL peuvent causer des problèmes lors de l’exécution de certaines requêtes SQL, car elles peuvent produire des résultats inattendus ou des erreurs. En particulier, les opérations mathématiques et les comparaisons logiques ne peuvent pas être effectuées sur des valeurs NULL, ce qui peut rendre difficile le traitement des données.
Si vous essayez d'effectuer une opération mathématique ou une comparaison logique sur une valeur NULL, le résultat sera également NULL. Cela peut rendre difficile le traitement des données dans certaines situations, en particulier lorsqu'il est nécessaire de faire des calculs sur les données ou de les comparer avec d'autres valeurs.

Solution

Pour résoudre ce problème, SQL fournit la fonction ISNULL. Cette fonction permet de remplacer les valeurs NULL par une valeur par défaut lors de l’exécution d’une requête

Par exemple, si vous avez une table “orders” avec une colonne “total” contenant le montant total de la commande, vous pouvez utiliser ISNULL pour remplacer les valeurs NULL par 0

La requête serait alors :

SELECT SUM(ISNULL(total, 0)) AS total_amount FROM orders;

Discussion

En utilisant la fonction ISNULL, vous pouvez manipuler et traiter efficacement les valeurs NULL dans vos requêtes SQL et éviter les erreurs potentielles qui pourraient survenir si vous ne traitez pas correctement ces valeurs. 

En résumé, bien que la présence de valeurs NULL en SQL puisse causer des problèmes lors de l’exécution de certaines requêtes SQL, il existe des moyens efficaces pour gérer ces situations et éviter les erreurs potentielles.

https://stackoverflow.com/questions/16840522/replacing-null-with-0-in-a-sql-server-query

mardi 28 décembre 2021

[Postgresql] pg_stat_activity

La table pg_stat_activity de PostgreSQL permet de surveiller les activités en cours dans la base de données. Il est important de surveiller l'état de la transaction dans cette table pour s'assurer que les transactions sont possibles. Si l'état est "idle", il est important de vérifier que le mode manuel de commit est activé pour permettre l'utilisation des transactions.

Voici un tableau comparatif des différents états de la table pg_stat_activity :

ÉtatSignification
activeLa session est en train d'exécuter une requête
idleLa session est connectée à la base de données mais n'exécute pas de requête
idle in transactionLa session est en mode manuel de commit et est en train d'exécuter une transaction
idle in transaction (aborted)La session a été annulée en raison d'une erreur de transaction

Pour passer en mode manuel de commit, il suffit d'exécuter la commande suivante :

sql
BEGIN;

Cette commande active le mode de transaction et permet de valider ou d'annuler les requêtes manuellement. Lorsque le mode manuel de commit est activé, l'état de la transaction dans la table pg_stat_activity passe de "idle" à "idle in transaction".

Exemple pratique : pour s'assurer que les transactions sont possibles, il faut vérifier que l'état de la transaction dans la table pg_stat_activity est "idle in transaction". Si ce n'est pas le cas, il faut activer le mode manuel de commit en exécutant la commande BEGIN.

En résumé, en surveillant attentivement la table pg_stat_activity et en comprenant les différents états de la transaction, il est possible de garantir l'utilisation efficace des transactions dans PostgreSQL.