[JAVA] Essayez d'exécuter ScalarDB sur WSL Ubuntu (exemple de création d'application)

Cet article traite de la création d'un exemple d'application et exécutons l'exemple d'application de ScalarDB.

Cliquez ici pour la construction de l'environnement (https://qiita.com/XCAT_SE/private/07969c960fb776d78990)

Opération ScalarDB

Il existe deux composants d'exploitation pour ScalarDB: le composant Stockage et le composant Transaction.

Composant de stockage

Ce composant a les fonctions suivantes.

De plus, le rôle de la clé correspond ici à la clé de partition et à la clé de cluster de Cassandra, et plusieurs définitions peuvent être faites sous la forme de liste ou séparées par des virgules.

En outre, le composant de stockage ScalarDB fournit quatre fonctions pour les opérations CRUD.

Composant de transaction

Ce composant fournit des capacités de transaction sans maître en plus de la fonctionnalité du composant de stockage.

Pour utiliser la fonctionnalité de transaction, vous devez d'abord obtenir une instance TransactionService. Ensuite, après avoir exécuté les opérations Get, Put, Delete et Scan sur l'instance TransactionService, validez l'instance TransactionService et reflétez les détails de l'opération dans la base de données.

Exemple d'application

Vérifiez le fonctionnement de l'application réelle de ScalarDB avec l'exemple d'application.

Aperçu de l'application

Implémentez un exemple d'application avec ces fonctionnalités.

image.png Diagramme d'image

Définition de schéma

image.png

KEYSPACE:emoney TABLE:account colonne ・ Group_id: ID de groupe (clé de partition) -Id: ID utilisateur (Clustering Key) ・ Solde: montant d'argent appartenant à l'utilisateur

Flux de processus

charge

  1. Obtenez des informations sur l'utilisateur spécifié
  2. Ajoutez le montant des frais aux informations utilisateur acquises
  3. Écrivez les informations mises à jour

Effectuez la série d'opérations ci-dessus en une seule transaction.

Paiement

  1. Obtenez des informations sur l'expéditeur et la destination
  2. Confirmez que le solde de la source du versement est supérieur au montant du versement
  3. Diminuez le montant envoyé par l'expéditeur et augmentez le montant envoyé au destinataire
  4. Écrivez les informations mises à jour

Effectuez la série d'opérations ci-dessus en une seule transaction.

Vérifier le solde

  1. Obtenez toutes les informations utilisateur
  2. Extraire les informations utilisateur une par une par traitement en boucle
  3. Récupérez le solde des informations utilisateur et affichez-le sur la console

Environnement

En supposant que l'application requise pour l'opération a déjà été installée, utilisez gradle pour obtenir le fichier jar d'exécution.

  1. Définissez le chemin vers Scalar DB Schema Tools

-Ajoutez le paramètre de chemin aux outils de schéma à .bash_profile ʻExport SCHEMATOOL = / home / (nom d'utilisateur de votre environnement) / scalarb / tools / schema`

・ Refléter le changement de réglage $ source ~/.bash_profile

  1. Définition du répertoire pour l'exemple de projet

・ Créer et déplacer un répertoire $ mkdir ~/scalardb_sample $ cd ~/scalardb_sample

-Exécuter la commande d'initialisation gradle $ gradle init --type java-application

  1. Créer un fichier de définition de gradle $ vi build.gradle

build.gradle


#Modifier la spécification de mainClassName(18e ligne)
#Changer avant
mainClassName = 'App'
#Après le changement
mainClassName = 'sample.emoney.ElectronicMoneyMain'
#Ajout de la définition de base de données scalaire aux dépendances(Ligne 22)
dependencies {
// This dependency is found on compile classpath of this component and consumers.
compile 'com.google.guava:guava:23.0'
compile group: 'com.scalar-labs', name: 'scalardb', version: '1.0.0'
// Use JUnit test framework
testCompile 'junit:junit:4.12'
  1. Obtenez le fichier jar d'exécution avec gradle $ gradle build

OK si BUILD SUCCESS FUL s'affiche

la mise en oeuvre

  1. Créez un fichier de schéma $ vi emoney.sdbql

emoney.sdbql


REPLICATION FACTOR 1;
CREATE NAMESPACE emoney;
CREATE TRANSACTION TABLE emoney.account (
 group_id TEXT PARTITIONKEY,
 id TEXT CLUSTERINGKEY,
 balance INT,
);
  1. Créez un schéma dans Casssandra à l'aide de l'outil Schema $ $SCHEMATOOL/loader emoney.sdbql

Vérifiez le schéma avec cqlsh $ cqlsh

Assurez-vous qu'il y a de l'argent dans l'espace de clé cqlsh> DESCRIBE KEYSPACES ;

Résultat d'exécution


emoney system_auth coordinator system_traces
system_schema system system_distributed

Assurez-vous qu'il y a un compte dans le tableau cqlsh> use emoney; cqlsh:emoney> DESCRIBE TABLES ;

Résultat d'exécution


account

Quitter cqlsh cqlsh:emoney> exit

Créez-en deux, un fichier de classe qui décrit le constructeur et la fonction, et un fichier de classe d'exécution qui reçoit des arguments et appelle la fonction.

Créer un répertoire et un fichier java $ mkdir -p src/main/java/sample/emoney $ cd src/main/java/sample/emoney $ vi ElectronicMoney.java

ElectronicMoney.java


package sample.emoney;

//Ajouter une importation
import com.google.inject.Guice; 
import com.google.inject.Injector; 
import com.scalar.database.config.DatabaseConfig; 
import com.scalar.database.service.StorageModule; 
import com.scalar.database.service.StorageService; 
import com.scalar.database.service.TransactionModule; 
import com.scalar.database.service.TransactionService; 

import java.io.File; 
import java.io.IOException; 

import com.scalar.database.api.DistributedTransaction; 
import com.scalar.database.api.Get; 
import com.scalar.database.api.Put; 
import com.scalar.database.api.Delete; 
import com.scalar.database.api.Result; 
import com.scalar.database.io.IntValue; 
import com.scalar.database.io.Key;
import com.scalar.database.io.TextValue; 
import com.scalar.database.exception.storage.ExecutionException; 
import com.scalar.database.exception.transaction.CommitException; 
import com.scalar.database.exception.transaction.CrudException; 
import com.scalar.database.exception.transaction.UnknownTransactionStatusException; 
import java.util.Optional;

import com.scalar.database.api.Scan; 
import com.scalar.database.api.Scanner;

public class ElectronicMoney {
  //Définir les variables de classe
  private final String NAMESPACE = "emoney";
  private final String TABLE_NAME = "account";
  private final String ID = "id";
  private final String GROUP_ID = "group_id";
  private final String BALANCE = "balance";
  private final StorageService storageService;
  private final TransactionService transactionService;

  //Implémenter le constructeur
  public ElectronicMoney() throws IOException {
   File prop_file = new File("/etc/scalar/database.properties");
   DatabaseConfig config = new DatabaseConfig(prop_file);
   Injector injector = Guice.createInjector(new StorageModule(config));
   storageService = injector.getInstance(StorageService.class);
   storageService.with(NAMESPACE, TABLE_NAME);
   injector = Guice.createInjector(new TransactionModule(config));
   transactionService = injector.getInstance(TransactionService.class);
   transactionService.with(NAMESPACE, TABLE_NAME);
  }

  public void charge(String groupId, String id, int amount) throws CrudException, CommitException, UnknownTransact ionStatusException {
   //Début de la transaction
   DistributedTransaction tx = transactionService.start();
   Key partitionKey = new Key(new TextValue(GROUP_ID, groupId));
   Key clusteringKey = new Key(new TextValue(ID, id));
   Get get = new Get(partitionKey, clusteringKey);
   Optional<Result> result = tx.get(get);
   int balance = amount;

   if (result.isPresent()) {
    int current = ((IntValue) result.get().getValue(BALANCE).get()).get();
    balance += current;
   }

   //Mettre à jour le solde
   Put put = new Put(partitionKey, clusteringKey).withValue(new IntValue(BALANCE, balance));
   tx.put(put);
   //Engagement de transaction
   tx.commit();
  }

  public void pay(String groupId, String fromId, String toId, int amount) throws CrudException,   CommitException, UnknownTransactionStatusException {
   //Début de la transaction
   DistributedTransaction tx = transactionService.start();
   //Obtenir les informations de compte de l'expéditeur et du destinataire
   Key partitionKey = new Key(new TextValue(GROUP_ID, groupId));
   Key fromKey = new Key(new TextValue(ID, fromId));
   Key toKey = new Key(new TextValue(ID, toId));
   Get fromGet = new Get(partitionKey, fromKey);
   Get toGet = new Get(partitionKey, toKey);
   Optional<Result> fromResult = tx.get(fromGet);
   Optional<Result> toResult = tx.get(toGet);

   if (!fromResult.isPresent()) {
    throw new RuntimeException(fromId + " doesn't exist.");
   }
   if (!toResult.isPresent()) {
    throw new RuntimeException(toId + " doesn't exist.");
   }
   int newFromBalance = ((IntValue) (fromResult.get().getValue(BALANCE).get())).get() - amount;
   int newToBalance = ((IntValue) (toResult.get().getValue(BALANCE).get())).get() + amount;
   if (newFromBalance < 0) {
    throw new RuntimeException(fromId + " doesn't have enough balances.");
   }
 
   //Mettre à jour le solde
   Put fromPut = new Put(partitionKey, fromKey).withValue(new IntValue(BALANCE, newFromBalance));
   Put toPut = new Put(partitionKey, toKey).withValue(new IntValue(BALANCE, newToBalance));
   tx.put(fromPut);   tx.put(toPut);
   //Engagement de transaction
   tx.commit();
  }

  public void balances(String groupId) throws ExecutionException {
   Key partitionKey = new Key(new TextValue(GROUP_ID, groupId));
   Scan scan = new Scan(partitionKey);
   Scanner scanner = storageService.scan(scan);
   scanner.forEach(r -> {
    r.getValue(ID).ifPresent(v -> System.out.print(((TextValue) v).getString().get()));
    System.out.print(" : ");
    r.getValue(BALANCE).ifPresent(v -> System.out.println(((IntValue) v).get()));
   });
  }

  public void deleteUser(String groupId, String id) throws CrudException, CommitException, UnknownTransactionStatu sException {
   //Début de la transaction
   DistributedTransaction tx = transactionService.start();
   Key partitionKey = new Key(new TextValue(GROUP_ID, groupId));
   Key clusteringKey = new Key(new TextValue(ID, id));
   Get get = new Get(partitionKey, clusteringKey);
   Optional<Result> result = tx.get(get);
   if (!result.isPresent()) {
    tx.abort();
    return;
   }

    //Mettre à jour le solde
   Delete delete = new Delete(partitionKey, clusteringKey);
   tx.delete(delete);
   //Engagement de transaction
   tx.commit();
  }

  public void close() {
   storageService.close();
   transactionService.close();
  }
}

$ vi ElectronicMoneyMain.java

ElectronicMoneyMain.java


package sample.emoney; 

public class ElectronicMoneyMain {
 public static void main(String[] args) throws Exception {
  String action = null;
  int amount = 0;
  String group = null;
  String to = null;
  String from = null;

  for (int i = 0; i < args.length; ++i) {
   if ("-action".equals(args[i])) {
    action = args[++i];
   } else if ("-group".equals(args[i])) {
    group = args[++i];
   } else if ("-amount".equals(args[i])) {
    amount = Integer.parseInt(args[++i]);
   } else if ("-to".equals(args[i])) {
    to = args[++i];
   } else if ("-from".equals(args[i])) {
    from = args[++i];
   } else if ("-help".equals(args[i])) {
    printUsageAndExit();
   }
  }

 ElectronicMoney eMoney = new ElectronicMoney();
 if (action.equalsIgnoreCase("charge")) {
   eMoney.charge(group, to, amount);
  } else if (action.equalsIgnoreCase("pay")) {
   if (from == null) {
   printUsageAndExit();
   }
   eMoney.pay(group, from, to, amount);
  } else if (action.equalsIgnoreCase("balances")) {
   eMoney.balances(group);
  } else if (action.equalsIgnoreCase("delete")) {
   eMoney.deleteUser(group, to);
  }
  eMoney.close();
 }

 private static void printUsageAndExit() {
  System.err.println(
   "ElectronicMoneyMain -action charge/pay/balances/delete -group id -to id [-amount number (needed for charge/pay)] [-from id (needed for pay)]"
  );
  System.exit(1);
 }
}

Courir

  1. Charge

1000 frais à l'utilisateur1 $ gradle run --args="-action charge -amount 1000 -group groupA -to user1"

0 frais à l'utilisateur2 $ gradle run --args="-action charge -amount 0 -group groupA -to user2"

Vérifiez le solde de l'utilisateur1 et de l'utilisateur2 $ gradle run --args="-action balances -group groupA" image.png

  1. Paiement

300 paiements de l'utilisateur1 à l'utilisateur2 $ gradle run --args="-action pay -amount 300 -group groupA -to user2 -from user1"

Vérifiez le solde de l'utilisateur1 et de l'utilisateur2 $ gradle run --args="-action balances -group groupA" image.png

  1. Suppression de l'utilisateur

Supprimer l'utilisateur1 $ gradle run --args="-action delete -group groupA -to user1"

Vérifiez le solde de l'utilisateur2 et confirmez que l'utilisateur1 a été supprimé $ gradle run --args="-action balances -group groupA" image.png

  1. Confirmation de la fonction de transaction

Modifiez ʻElectronicMoney.java` pour vous assurer que la fonction de transaction fonctionne.

$ vi ElectronicMoney.java

ElectronicMoney.java(fonction de paye,Près de la ligne 101)


  public void pay(String groupId, String fromId, String toId, int amount) throws CrudException,   CommitException, UnknownTransactionStatusException {
   //Début de la transaction
   DistributedTransaction tx = transactionService.start();
   //Obtenir les informations de compte de l'expéditeur et du destinataire
   Key partitionKey = new Key(new TextValue(GROUP_ID, groupId));
   Key fromKey = new Key(new TextValue(ID, fromId));
   Key toKey = new Key(new TextValue(ID, toId));
   Get fromGet = new Get(partitionKey, fromKey);
   Get toGet = new Get(partitionKey, toKey);
   Optional<Result> fromResult = tx.get(fromGet);
   Optional<Result> toResult = tx.get(toGet);

   if (!fromResult.isPresent()) {
    throw new RuntimeException(fromId + " doesn't exist.");
   }
   if (!toResult.isPresent()) {
    throw new RuntimeException(toId + " doesn't exist.");
   }
   int newFromBalance = ((IntValue) (fromResult.get().getValue(BALANCE).get())).get() - amount;
   int newToBalance = ((IntValue) (toResult.get().getValue(BALANCE).get())).get() + amount;
   if (newFromBalance < 0) {
    throw new RuntimeException(fromId + " doesn't have enough balances.");
   }
 
   //Mettre à jour le solde
   Put fromPut = new Put(partitionKey, fromKey).withValue(new IntValue(BALANCE, newFromBalance));
   // ----------------Lignes supplémentaires d'ici-----------------------
   //Ajouter une instruction qui génère toujours une erreur pour l'expérimentation
   if (newFromBalance >= 0){
    throw new RuntimeException("test error.");
   }
   // ----------------Lignes supplémentaires jusqu'à ici-----------------------
   //Le solde du destinataire n'est pas mis à jour
   Put toPut = new Put(partitionKey, toKey).withValue(new IntValue(BALANCE, newToBalance));
   tx.put(fromPut);   tx.put(toPut);
   //Engagement de transaction
   tx.commit();
  }

1000 frais à l'utilisateur1 $ gradle run --args="-action charge -amount 1000 -group groupA -to user1"

0 frais à l'utilisateur2 $ gradle run --args="-action charge -amount 0 -group groupA -to user2"

Vérifiez le solde avant l'exécution gradle run --args="-action balances -group groupA" image.png Essayez d'exécuter le processus de remise gradle run --args="-action pay -amount 300 -group groupA -to user2 -from user1"

C'est tout pour exécuter l'exemple d'application. Merci pour la lecture.

Recommended Posts

Essayez d'exécuter ScalarDB sur WSL Ubuntu (exemple de création d'application)
Essayez d'exécuter ScalarDB sur WSL Ubuntu (Construction de l'environnement)
Essayez de mettre Docker dans ubuntu sur WSL
Essayez DisplayLink sur Ubuntu 20.04
Installez Java sur WSL Ubuntu 18.04
Essayez d'exécuter Spring Boot sur Kubernetes
Installation d'Elmer / Ice (Ubuntu sur WSL)
Nouvelle commande de création de l'application Ruby on Rails
Utiliser cljstyle avec Spacemacs sur Ubuntu sur WSL2
Configurer un serveur SSH sur Ubuntu 20.04, qui est WSL2
Docker sur Ubuntu18.04 sur WSL2 et instructions d'installation de VSCode