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

picodata-jdbc

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

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

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

Подключение

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

<dependency>
    <groupId>io.picodata</groupId>
    <artifactId>picodata-jdbc</artifactId>
    <version>LATEST</version>
</dependency>

Вместо LATEST можно также указать и конкретную версию коннектора.

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

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

Поддерживаемые возможности

JDBC-драйвер для Picodata использует протокол PGPROTO и поддерживает некоторые настройки подключения драйвера PgJDBC. Реализован класс io.picodata.Driver, имплементирующий java.sql.Driver. В качестве адреса для подключения следует использовать формат jdbc:picodata://host:port/?user=sqluser,password=P@ssw0rd.

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

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

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

Примечание

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

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

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

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

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

docker-compose up -d

3. Создайте отдельного пользователя для подключения по JDBC и выдайте ему права на создание таблиц:

docker-compose exec picodata-1 bash -c "echo -ne \"CREATE USER \\\"sqluser\\\" WITH PASSWORD 'P@ssw0rd' USING md5;\nGRANT CREATE TABLE TO \\\"sqluser\\\";\" | picodata admin /home/picouser/picodata-1/admin.sock"

4. Вернитесь в исходную директорию picodata-jdbc-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

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

19:09:22.473 [io.picodata.PicodataJDBCExample.main()] INFO  io.picodata.PicodataJDBCExample - Connected to the Picodata server successfully.
19:09:22.491 [io.picodata.PicodataJDBCExample.main()] INFO  io.picodata.PicodataJDBCExample - Executed file before.sql
19:09:22.608 [io.picodata.PicodataJDBCExample.main()] INFO  io.picodata.PicodataJDBCExample - 1 rows was deleted
19:09:22.640 [io.picodata.PicodataJDBCExample.main()] INFO  io.picodata.PicodataJDBCExample - 1 rows was inserted
19:09:22.674 [io.picodata.PicodataJDBCExample.main()] INFO  io.picodata.PicodataJDBCExample - Id is 1, name is Dima
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

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

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

    ├── pom.xml
    └── src
        └── main
            ├── java
            │   └── io
            │       └── picodata
            │           └── PicodataJDBCExample.java
            └── resources
                ├── docker-compose.yaml
                └── 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-jdbc-example</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>io.picodata</groupId>
            <artifactId>picodata-jdbc</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.0.16</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.11.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.PicodataJDBCExample</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

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

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PicodataJDBCExample {
    private static Logger logger = LoggerFactory.getLogger(PicodataJDBCExample.class);

    public static void main(String[] args) {
        var props = new Properties();
        props.setProperty("user", "sqluser");
        props.setProperty("password", "P@ssw0rd");
        props.setProperty("sslmode", "disable");

        var connstr = "jdbc:picodata://localhost:5432/";
        try (Connection conn = DriverManager.getConnection(connstr, props)) {
            logger.info("Connected to the Picodata server successfully.");

            var stmt = conn.createStatement();

            try {
                Files.readAllLines(Paths.get("before.sql")).stream().forEach(statement -> {
                    try {
                        stmt.execute(statement);
                    } catch (SQLException e) {
                        throw new RuntimeException(e);
                    }
                });
                logger.info("Executed file before.sql");
            } catch (RuntimeException e) {
                logger.error("Failed to execute before.sql", e);
                System.exit(1);
            } catch (IOException e) {
                logger.error("Failed to open file before.sql", e);
                System.exit(1);
            }

            var deleteQuery = "DELETE FROM \"warehouse\";";
            var preparedStmt = conn.prepareStatement(deleteQuery);
            var deleteRows = preparedStmt.executeUpdate();
            logger.info("{} rows were deleted", deleteRows);


            var insertQuery = "INSERT INTO \"warehouse\" VALUES (?, ?);";
            preparedStmt = conn.prepareStatement(insertQuery);
            preparedStmt.setInt(1, 1);
            preparedStmt.setString(2, "Dima");
            var insertedRows = preparedStmt.executeUpdate();
            logger.info("{} rows were inserted", insertedRows);

            var selectQuery = "SELECT * FROM \"warehouse\" WHERE id = ?;";
            preparedStmt = conn.prepareStatement(selectQuery);
            preparedStmt.setInt(1, 1);
            var res = preparedStmt.executeQuery();
            while (res.next()) {
                logger.info("Id is {}, name is {}", res.getInt(1), res.getString(2));
            }

        } catch (SQLException e) {
            logger.error("Unexpected error: ", e);
            System.exit(1);
        }
    }
}
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_ID: picodata-1
    PICODATA_DATA_DIR: picodata-1
    PICODATA_LISTEN: picodata-1:3301
    PICODATA_ADVERTISE: picodata-1:3301
    PICODATA_PEER: picodata-1:3301
    PICODATA_PG_LISTEN: picodata-1:5432
    PICODATA_PG_SSL: "false"
    ports:
    - "3301:3301"
    - "5432:5432"

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_ID: 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_ID: 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>