Явская библиотека, чтобы написать двоичный формат для КОПИИ Пост-ГРЭС?

Сделал, чтобы любой столкнулся с Явской библиотекой (или просто некоторый код), чтобы написать набор из двух предметов формат, используемый Пост-ГРЭС Команда КОПИИ?

Это выглядит очень простым, но если бы чей-то уже вычисленный правильный формат данных кортежа, я точно также начал бы там.

На самом деле даже просто описание форматов для всех типов данных было бы полезно.

Спасибо.

5
nl ja de

3 ответы

Вы могли попробовать PgBulkInsert, который осуществляет Двойной Протокол Копии PostgreSQL:

Это также доступно от Центрального репозитория Знатока.

Отказ от ответственности: Я - автор проекта.

Набор из двух предметов PostgreSQL копирует протокол

Я не хочу просто рекламировать свой проект, но также и писать о протоколе.

First of all I have written a class PgBinaryWriter, which wraps a DataOutputStream and has methods for writing the Binary Protocol Header, a method to start a new row (the Binary Copy Protocol requires you to write the number of columns for each row you are going to insert) and a write method, which takes an IValueHandler for writing a given Java type.

PgBinaryWriter осуществляет AutoClosable , потому что необходимо написать -1 к потоку прежде, чем смыть и закрыть поток.

The IValueHandler takes a DataOutputStream and a value. It is responsible for writing the given value with the PostgreSQL Binary Protocol Format.

PgBinaryWriter

// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package de.bytefish.PgBulkInsert.de.bytefish.PgBulkInsert.pgsql;


import de.bytefish.PgBulkInsert.de.bytefish.PgBulkInsert.exceptions.BinaryWriteFailedException;
import de.bytefish.PgBulkInsert.de.bytefish.PgBulkInsert.pgsql.handlers.IValueHandler;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.OutputStream;

public class PgBinaryWriter implements AutoCloseable {

    /** The ByteBuffer to write the output. */
    private transient DataOutputStream buffer;

    public PgBinaryWriter() {
    }

    public void open(final OutputStream out) {
        buffer = new DataOutputStream(new BufferedOutputStream(out));

        writeHeader();
    }

    private void writeHeader() {
        try {

           //11 bytes required header
            buffer.writeBytes("PGCOPY\n\377\r\n\0");
           //32 bit integer indicating no OID
            buffer.writeInt(0);
           //32 bit header extension area length
            buffer.writeInt(0);

        } catch(Exception e) {
            throw new BinaryWriteFailedException(e);
        }
    }

    public void startRow(int numColumns) {
        try {
            buffer.writeShort(numColumns);
        } catch(Exception e) {
            throw new BinaryWriteFailedException(e);
        }
    }

    public  void write(final IValueHandler handler, final TTargetType value) {
        handler.handle(buffer, value);
    }

    @Override
    public void close() {
        try {
            buffer.writeShort(-1);

            buffer.flush();
            buffer.close();
        } catch(Exception e) {
            throw new BinaryWriteFailedException(e);
        }
    }
}

ValueHandler

IValueHandler является простым интерфейсом, у которого есть ручка метод, чтобы взять DataOutputStream и стоимость.

// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package de.bytefish.PgBulkInsert.de.bytefish.PgBulkInsert.pgsql.handlers;

import java.io.DataOutputStream;
import java.lang.reflect.Type;

public interface IValueHandler extends ValueHandler {

    void handle(DataOutputStream buffer, final TTargetType value);

    Type getTargetType();

}

Важно знать о протоколе, что необходимо написать -1 , когда стоимость пустая. Для этого я написал абстрактный базовый класс, который обращается со случаем.

// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package de.bytefish.PgBulkInsert.de.bytefish.PgBulkInsert.pgsql.handlers;

import de.bytefish.PgBulkInsert.de.bytefish.PgBulkInsert.exceptions.BinaryWriteFailedException;

import java.io.DataOutputStream;

public abstract class BaseValueHandler implements IValueHandler {

    @Override
    public void handle(DataOutputStream buffer, final T value) {
        try {
            if (value == null) {
                buffer.writeInt(-1);
                return;
            }
            internalHandle(buffer, value);
        } catch (Exception e) {
            throw new BinaryWriteFailedException(e);
        }
    }

    protected abstract void internalHandle(DataOutputStream buffer, final T value) throws Exception;
}

Тогда укладчики для различных Явских типов могут осуществленный. Вот является пример для долго . Можно найти другие внедрения в хранилище GitHub (укладчики).

// Copyright (c) Philipp Wagner. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package de.bytefish.PgBulkInsert.de.bytefish.PgBulkInsert.pgsql.handlers;

import java.io.DataOutputStream;
import java.lang.reflect.Type;

public class LongValueHandler extends BaseValueHandler {

    @Override
    protected void internalHandle(DataOutputStream buffer, final Long value) throws Exception {
        buffer.writeInt(8);
        buffer.writeLong(value);
    }

    @Override
    public Type getTargetType() {
        return Long.class;
    }
}

Используя PgBinaryWriter

Теперь это наконец приходит к соединению частей. Пожалуйста, обратите внимание на то, что я резюмировал еще некоторые части. Это могло бы быть необходимо для поиска больше деталей внедрения в коде.

public abstract class PgBulkInsert {

   //... 

    public void saveAll(PGConnection connection, Stream entities) throws SQLException {

        CopyManager cpManager = connection.getCopyAPI();
        CopyIn copyIn = cpManager.copyIn(getCopyCommand());

        int columnCount = columns.size();

        try (PgBinaryWriter bw = new PgBinaryWriter()) {

           //Wrap the CopyOutputStream in our own Writer:
            bw.open(new PGCopyOutputStream(copyIn));

           //Insert all entities:                
            entities.forEach(entity -> {

               //Start a New Row:
                bw.startRow(columnCount);

               //Insert the Column Data:
                columns.forEach(column -> {
                    try {
                        column.getWrite().invoke(bw, entity);
                    } catch (Exception e) {
                        throw new SaveEntityFailedException(e);
                    }
                });
            });
        }
    }

    private String getCopyCommand()
    {
        String commaSeparatedColumns = columns.stream()
                .map(x -> x.columnName)
                .collect(Collectors.joining(", "));

        return String.format("COPY %1$s(%2$s) FROM STDIN BINARY",
                table.GetFullQualifiedTableName(),
                commaSeparatedColumns);
    }
}

PgBulkInsert

PgBulkInsert поддерживает следующие типы данных PostgreSQL.

Основное использование

Предположите, что большое количество людей должно быть большой частью, вставленной в базу данных PostgreSQL. Каждый у Человека есть имя, фамилия и дата рождения.

Таблица базы данных

Стол в базе данных PostgreSQL мог бы быть похожим на это:

CREATE TABLE sample.unit_test
(
    first_name text,
    last_name text,
    birth_date date
);

Модель предметной области

The Модель предметной области in the application might look like this:

private class Person {

    private String firstName;

    private String lastName;

    private LocalDate birthDate;

    public Person() {}

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public LocalDate getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(LocalDate birthDate) {
        this.birthDate = birthDate;
    }

}

Оптовая вставка

Then you have to implement the PgBulkInsert, which defines the mapping between the table and the Модель предметной области.

public class PersonBulkInserter extends PgBulkInsert
{
    public PersonBulkInserter() {
        super("sample", "unit_test");

        MapString("first_name", Person::getFirstName);
        MapString("last_name", Person::getLastName);
        MapDate("birth_date", Person::getBirthDate);
    }
}

Using the Оптовая вставка

И наконец мы можем написать Тест Единицы, чтобы вставить 100000 Люди в базу данных. Можно найти весь Тест Единицы на GitHub: IntegrationTest.java.

@Test
public void bulkInsertPersonDataTest() throws SQLException {
   //Create a large list of Persons:
    List persons = getPersonList(100000);

   //Create the BulkInserter:
    PersonBulkInserter personBulkInserter = new PersonBulkInserter();

   //Now save all entities of a given stream:
    personBulkInserter.saveAll(PostgreSqlUtils.getPGConnection(connection), persons.stream());

   //And assert all have been written to the database:
    Assert.assertEquals(100000, getRowCount());
}

private List getPersonList(int numPersons) {
    List persons = new ArrayList<>();

    for (int pos = 0; pos < numPersons; pos++) {
        Person p = new Person();

        p.setFirstName("Philipp");
        p.setLastName("Wagner");
        p.setBirthDate(LocalDate.of(1986, 5, 12));

        persons.add(p);
    }

    return persons;
}
4
добавлено

Вы рассмотрели просто использование CopyManager от водителя JDBC? Иначе можно, вероятно, получить внедрение из QueryExecutorImpl.

2
добавлено
@Dmitri: CopyManager.copyOut() был бы производить двоичные данные (от базы данных). Если ваши данные еще не в столе, то это wouldn' t помогают, конечно.
добавлено автор a_horse_with_no_name, источник
Мое понимание - то, что , CopyManager только перенаправляет потоки ввода/вывода, он все еще, требует, чтобы правильно форматированные данные загрузили, нет? В любом случае я должен быть в состоянии произвести файлы оптового груза без связи JDBC.
добавлено автор Dmitri, источник
Внедрение водителя полезно, но поиск фактического кодирования, я могу только найти внедрение для примитивов, массивов байтов и Последовательностей (в PGStream ), которые довольно очевидны. Можно ли указать мне туда, где это обращается с более составными типами (например, время/дата, множества, пользовательские типы, и т.д.)?
добавлено автор Dmitri, источник
TimeStampUtils.toTimeBin (), .toDateBin (), .toTimestampBin() описывают форматы даты, вид, с большим количеством условных предложений. Кодекс C в utils/backend/adt/timestamp.c так зависит от вариантов времени компиляции I' m испуганный, чтобы коснуться этого двоичного формата 10-футовым полюсом. Вы считали что-нибудь полезным в ваших путешествиях?
добавлено автор MZS, источник
1
добавлено
pro.jvm
pro.jvm
3 503 участник(ов)

Сообщество разработчиков Java Scala Kotlin Groovy Clojure Чат для нач-их: @javastart Наш сайт: projvm.com projvm.ru Наш канал: @proJVM Вакансии: @jvmjobs Конфы: @jvmconf

pgsql – PostgreSQL
pgsql – PostgreSQL
2 429 участник(ов)

Чат про PostgreSQL

Java & Co
Java & Co
2 370 участник(ов)

Можно обсуждать с матом и без всё, что касается жабы, вплоть до холиваров. НЕ ИМЕЕТ ОТНОШЕНИЯ К САЙТУ JAVARUSH.RU ПРАВИЛА - https://t.me/javarush/75723 Вакансии сюда - https://telegram.me/joinchat/B7IzvUCnfo6d8t3yIxKguQ По вопросам - @thedude

learn.java
learn.java
1 888 участник(ов)

Чат для начинающих и не только Статистика: https://combot.org/chat/-1001083535868 Основной чат - @jvmchat

DBA - русскоговорящее сообщество
DBA - русскоговорящее сообщество
1 345 участник(ов)

Общаемся и обсуждаем темы, посвященные DBA, PostgreSQL, Redis, MongoDB, MySQL, neo4j, riak и т.д. См. также: @devops_ru, @kubernetes_ru, @docker_ru, @nodejs_ru Рекомендуем сразу отключить уведомления, чтобы пребывание здесь было полезным и комфортным.

Java Underground
Java Underground
169 участник(ов)

https://vk.com/javatutorial

Javanese Questions
Javanese Questions
109 участник(ов)

Чат предназначен для обмена знаниями строго в формате в вопрос-ответ. Тема — Java, Kotlin и Android. Вопрос должен быть предварительно прогуглен, понятно и грамотно сформулирован, помечен хэштегами. Ответ — тем более. Куски кода размером в несколько строк можно писать прямо здесь, для больших кусков кода стоит использовать http://gist.github.com/, http://pastebin.com/, https://codeshare.io/ или любой аналогичный сервис. В некоторых случаях можно прикреплять скриншоты. Стикеры и гифки запрещены. Дополнять и уточнять вопросы и ответы — редактированием исходного сообщения. Обсуждения должны приводить к редактированию вопроса/ответа и удаляться. По хештегам можно искать существующие вопросы и овтеты: #вопрос #ответ #git #generics #java #server #awt #javafx #swing #kotlin #anko #tornadofx #ktor #android #recyclerView #performance #arch #network #permissions #storage #async