Перейти к содержанию

picodata-java

В данном разделе приведено описание picodata-java — Java-драйвера для работы с СУБД Picodata.

Общие сведения

Драйвер предоставляет Java API для работы с низкоуровневым Picodata API и служит коннектором к СУБД Picodata из Java-приложений. Драйвер совместим с кластерами Picodata, использующими библиотеку шардирования vshard.

Подключение

Для подключения коннектора следует добавить его в проект в качестве зависимости. Пример для Maven:

<dependency>
  <groupId>io.picodata</groupId>
  <artifactId>picodata-java</artifactId>
</dependency>

Также в pom.xml вашего приложения или в глобальные настройки Maven необходимо будет добавить репозиторий Picodata:

    <repositories>
        <repository>
            <id>binary.picodata.io</id>
            <url>https://binary.picodata.io/repository/maven-releases/</url>
        </repository>
    </repositories>

Проверка работы

Мы предоставляем тестовое Java-приложение, которое создает и заполняет таблицу в Picodata посредством коннектора picodata-java.

Для проверки работы тестового приложения потребуются JDK (например, OpenJDK) версии 1.8 или новее, и Docker.

Примечание

Проверить наличие необходимой версии JDK можно командой ./mvnw --version (строка Java version) в директории проекта picodata-java.

Порядок действий:

1. Склонируйте репозиторий тестового приложения и соберите его:

git clone https://git.picodata.io/picodata/picodata/examples/-/tree/master/picodata-java-example
./mvnw install

2. Перейдите в директорию src/main/resources и запустите контейнеры с тестовым кластером Picodata:

docker-compose up -d

3. Настройте авторизацию для Picodata в контейнере:

docker-compose exec picodata-1 bash -c "echo -ne \"ALTER USER \\\"admin\\\" WITH PASSWORD 'P@ssw0rd';\" | picodata admin /home/picouser/picodata-1/admin.sock"

4. Вернитесь в исходную директорию picodata-java-example и запустите тестовое приложение.

Для версии JDK 17 и выше:

_JAVA_OPTIONS="--add-exports=java.base/sun.nio.ch=ALL-UNNAMED --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED --add-opens=java.base/sun.nio.ch=ALL-UNNAMED" ./mvnw exec:java

Для более старых версий:

./mvnw exec:java

Результатом успешной работы будет вставка строки в тестовую таблицу и вывод содержимого таблицы:

[nioEventLoopGroup-2-1] INFO  i.p.d.c.c.AbstractTarantoolConnectionManager - Connected to Tarantool server at /127.0.0.1:3301
Insert result:
row_count 1
Select all characters after insert:
metadata [{name=id, type=integer}, {name=name, type=string}, {name=year, type=integer}]
rows [[2, Vasya, 2000]]
[io.picodata.PicodataExample.main()] INFO  i.p.d.c.c.AbstractTarantoolConnectionManager - Disconnected from /127.0.0.1:3301

Структура приложения

Ниже показано дерево файлов минимального тестового приложения:

├── pom.xml
├── src
│   └── main
│       ├── java
│       │   └── com
│       │       └── example
│       │           └── PicodataExample.java
│       └── resources
│           ├── docker-compose.yml
│           └── logback.xml

Содержимое файлов тестового приложения:

pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>io.picodata</groupId>
    <artifactId>picodata-java-example</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>io.picodata</groupId>
            <artifactId>picodata-java</artifactId>
            <version>1.0.2</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.3.4</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.2.0</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <fork>true</fork>
                    <debug>true</debug>
                    <optimize>true</optimize>
                    <showDeprecation>true</showDeprecation>
                    <showWarnings>true</showWarnings>
                    <source>17</source>
                    <target>17</target>
                    <excludes>
                        <exclude>**/package-info.java</exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>3.4.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>io.picodata.PicodataExample</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>binary.picodata.io</id>
            <url>https://binary.picodata.io/repository/maven-releases/</url>
        </repository>
    </repositories>
</project>
PicodataExample.java
package io.picodata;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import io.picodata.driver.api.TarantoolClient;
import io.picodata.driver.api.TarantoolClientFactory;
import io.picodata.driver.api.TarantoolResult;
import io.picodata.driver.api.tuple.DefaultTarantoolTupleFactory;
import io.picodata.driver.api.tuple.TarantoolTuple;
import io.picodata.driver.api.tuple.TarantoolTupleFactory;
import io.picodata.driver.mappers.factories.DefaultMessagePackMapperFactory;


public class PicodataExample {

    private static final DefaultMessagePackMapperFactory mapperFactory = DefaultMessagePackMapperFactory.getInstance();
    private static final TarantoolTupleFactory tupleFactory =
            new DefaultTarantoolTupleFactory(mapperFactory.defaultComplexTypesMapper());

    static TarantoolClient<TarantoolTuple, TarantoolResult<TarantoolTuple>> setupClient() {
        return TarantoolClientFactory.createClient()
            // If any addresses or an address provider are not specified,
            // the default host 127.0.0.1 and port 3301 are used
            .withAddress("127.0.0.1", 3301)
            // For connecting to a Cartridge application, use the value of cluster_cookie parameter in the init.lua file
            .withCredentials("admin", "P@ssw0rd")
            // you may also specify more client settings, such as:
            // timeouts, number of connections, custom MessagePack entities to Java objects mapping, etc.
            .build();
    }

    public static void main(String[] args) throws Exception {
        try (TarantoolClient<TarantoolTuple, TarantoolResult<TarantoolTuple>> client = setupClient()) {
            client.callForSingleResult(
                "pico.sql",
                Arrays.asList(
                    "CREATE TABLE \"characters\" (" +
                    "\"id\" INT PRIMARY KEY, \"name\" TEXT, \"year\" INT" +
                    ") distributed by (\"id\")"
                ),
                HashMap.class
            ).get();

            client.callForSingleResult(
                "pico.sql",
                Arrays.asList("DELETE FROM \"characters\" WHERE 1=1"),
                HashMap.class
            ).get();

            String query = "INSERT INTO \"characters\" VALUES (?, ?, ?)";
            TarantoolTuple queryTuple = tupleFactory.create(Arrays.asList(2, "Vasya", 2000));

            Map<String, Object> result =
                client.callForSingleResult(
                    "pico.sql",
                    Arrays.asList(query, queryTuple),
                    HashMap.class
                ).get();

            String query2 = "SELECT * FROM \"characters\" WHERE \"id\" = ?";
            TarantoolTuple queryTuple2 = tupleFactory.create(Arrays.asList(2));

            Map<String, Object> result2 =
                client.callForSingleResult(
                    "pico.sql",
                    Arrays.asList(query2, queryTuple2),
                    HashMap.class
                ).get();

            System.out.println("Insert result:");
            result.forEach((key, value) -> System.out.println(key + " " + value));
            System.out.println("Select all characters after insert:");
            result2.forEach((key, value) -> System.out.println(key + " " + value));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.exit(0);
        }
    }
}
docker-compose.yml
---
version: '3'

services:
  picodata-1:
    image: docker-public.binary.picodata.io/picodata:24.4.1
    container_name: picodata-1
    hostname: picodata-1
    environment:
      PICODATA_INSTANCE_NAME: picodata-1
      PICODATA_DATA_DIR: picodata-1
      PICODATA_LISTEN: picodata-1:3301
      PICODATA_ADVERTISE: picodata-1:3301
      PICODATA_PEER: picodata-1:3301
    ports:
      - "3301:3301"

  picodata-2:
    image: docker-public.binary.picodata.io/picodata:24.4.1
    container_name: picodata-2
    hostname: picodata-2
    depends_on:
      - picodata-1
    environment:
      PICODATA_INSTANCE_NAME: picodata-2
      PICODATA_DATA_DIR: picodata-2
      PICODATA_LISTEN: picodata-2:3302
      PICODATA_ADVERTISE: picodata-2:3302
      PICODATA_PEER: picodata-1:3301
    ports:
      - "3302:3302"


  picodata-3:
    image: docker-public.binary.picodata.io/picodata:24.4.1
    container_name: picodata-3
    hostname: picodata-3
    depends_on:
      - picodata-1
    environment:
      PICODATA_INSTANCE_NAME: picodata-3
      PICODATA_DATA_DIR: picodata-3
      PICODATA_LISTEN: picodata-3:3303
      PICODATA_ADVERTISE: picodata-3:3303
      PICODATA_PEER: picodata-1:3301
    ports:
      - "3303:3303"
logback.xml
<configuration debug="true">
    <variable name="logLevel" value="${logging.logLevel}"/>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="${logLevel:-INFO}">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>