Skip to content
Java library for efficient Bulk Inserts to PostgreSQL using the Binary COPY Protocol.
Java Batchfile
Branch: master
Clone or download
bytefish Merge pull request #42 from Hixon10/patch-1
Remove duplicate link to documentation
Latest commit 87059c7 Oct 5, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
PgBulkInsert Remove JavaDoc Comments Aug 10, 2019
.gitignore Issue #32 Increase Version Number to 3.3 Dec 26, 2018
LICENSE Update LICENSE Nov 24, 2018 Remove duplicate link to documentation Oct 5, 2019


PgBulkInsert is a Java library for Bulk Inserts to PostgreSQL using the Binary COPY Protocol.

It provides a wrapper around the PostgreSQL COPY command:

The COPY command is a PostgreSQL specific feature, which allows efficient bulk import or export of data to and from a table. This is a much faster way of getting data in and out of a table than using INSERT and SELECT.

This project wouldn't be possible without the great Npgsql library, which has a beautiful implementation of the Postgres protocol.


PgBulkInsert is available in the Central Maven Repository.

You can add the following dependencies to your pom.xml to include PgBulkInsert in your project.


Supported PostgreSQL Types


PgBulkInsert is released with under terms of the MIT License:

Basic Usage

Imagine we want to bulk insert a large amount of persons into a PostgreSQL database. Each Person has a first name, a last name and a birthdate.

Database Table

The table in the PostgreSQL database might look like this:

 CREATE TABLE sample.unit_test
    first_name text,
    last_name text,
    birth_date date

Domain Model

The domain model 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;

Bulk Inserter

Then you have to implement the AbstractMapping<Person>, which defines the mapping between the table and the domain model.

public class PersonMapping extends AbstractMapping<Person>
    public PersonMapping() {
        super("sample", "unit_test");

        mapText("first_name", Person::getFirstName);
        mapText("last_name", Person::getLastName);
        mapDate("birth_date", Person::getBirthDate);

This mapping is used to create the PgBulkInsert<Person>:

PgBulkInsert<Person> bulkInsert = new PgBulkInsert<Person>(new PersonMapping());

Using the Bulk Inserter

And finally we can write a Unit Test to insert 100000 Persons into the database. You can find the entire Unit Test on GitHub as

public void bulkInsertPersonDataTest() throws SQLException {
    // Create a large list of Persons:
    List<Person> persons = getPersonList(100000);
    // Create the BulkInserter:
    PgBulkInsert<Person> bulkInsert = new PgBulkInsert<Person>(new PersonMapping());
    // Now save all entities of a given stream:
    // And assert all have been written to the database:
    Assert.assertEquals(100000, getRowCount());

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

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

        p.setBirthDate(LocalDate.of(1986, 5, 12));


    return persons;



You can’t perform that action at this time.