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_NAME: 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_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>