Postgres

To test against Postgres docker test container set the platform to postgres in src/test/resources/application-test.yaml

Refer to docs / testing if application-test.yaml doesn't exist yet.

ebean:
  test:
    platform: postgres # h2, postgres, ...
    ddlMode: dropCreate # none | dropCreate | migrations | create
    dbName: my_app

That is all we need to do. Running tests via IDE, maven or gradle will all automatically setup a docker test container for postgres including creating the database and user etc.

The above will use the following defaults:

username:{dbName}
password:test
port:6432
url:jdbc:postgresql://localhost:{port}/{dbName}
image:postgres:{version:12}

ebean-postgres dependency

We can use the io.ebean:ebean-postgres dependency rather than io.ebean:ebean if we want to only bring in the Postgres specific platform code. Depending on io.ebean:ebean will bring in all platforms.

Postgres types

UUID

UUID is mapped to native Postgres UUID type.

INET

java.net.InetAddress and io.ebean.types.Inet are both automatically mapped to native Postgres INET type. When using InetAddress we need to take care that it doesn't perform unwanted DNS lookup validating addresses. io.ebean.types.Inet is a simple value type.

Array types - @DbArray

We use @DbArray to map Lists or Sets of UUID, String, Enums, Number types. These are mapped to Postgres array types like uuid[], varchar[], integer[] ...

For more on Postgres Array types.

JSON / JSONB - @DbJson

We can use @DbJson and @DbJsonB to map content to Postgres JSON or JSONB types.

HSTORE - @DbMap

We can use @DbMap to map Map<String,String> properties to Postgres HSTORE type.

Postgres ANY

Postgres has an ANY operator which allows binding an Array of values. This can provide a very big benefit when using = ANY(?) rather than the usual IN (?,?,? ...) when the number of bind values for an IN clause is variable. Effectively no matter the number of bind values with Postgres = ANY we get to use the exact same SQL. This means we need only use a single Ebean query plan, a single JDBC PreparedStatement and the database server also only see the one sql statement and typically means that it only needs to parse that once to determine the query plan ("the database has to do less hard parsing").

For these reasons Ebean will use Postgres = ANY whenever it can rather than use a IN clause.

Additionally you often want to use = ANY in SQL statements for DtoQuery and SqlQuery.

History support

History support for Postgres is provided by generating triggers and history table.

Table Partitioning

Postgres 10 added support for table partitioning. We use @DbPartition to define the table should have range partitioning based on DAY, WEEK, MONTH or YEAR.

@DbPartition(mode = DAY, property = "eventTime")
@Entity
@Table(name = "event")
public class DEvent extends BaseDomain {
  ...

Extensions

We may want to use extensions like hstore and pgcrypto. Note that when using ebean-test with docker it will automatically add those 2 extensions by default.

We can specify extensions that should be installed automatically via:

ebean:
  test:
    platform: postgres #, h2, postgres, mysql, oracle, sqlserver
    ddlMode: dropCreate # none | dropCreate | migrations | create
    dbName: myapp
    postgres:
      extensions: pgcrypto, hstore

Schema

With Postgres it could be considered good practice to create our tables into a named schema (and not the public schema). If we want to do this we have made this easy in Ebean version 11.18.2 where we can specify ebean.dbSchema and this is then used for both DB migrations and create-all.sql.

It is advisable that the DB User matches the DB Schema. When this is done then there is no need to use currentSchema or modify the search path. For example, if I want to use a schema called myapp it is advisable to have the DB user/role match and be myapp.

application.yaml
ebean:
  dbSchema: myapp  ## use this database schema
DatabaseConfig
databaseConfig.setDbSchema("myapp");

Docker container

We can programmatically start a docker container version of Postgres. This can be a useful way to run an application locally.

The below uses ebean-test-docker dependency which already comes with ebean-test. If we do not have a dependency on ebean-test then add io.ebean:ebean-test-docker:5.0 as a dependency.

package main;

import io.ebean.docker.commands.PostgresContainer;

public class StartPostgres {

  public static void main(String[] args) {

    PostgresContainer container = PostgresContainer.newBuilder("14")
      // .port(5432) // Note: defaults to 6432
      .dbName("my_app")
      .user("my_app")
      .password("silly")
      .containerName("pg14x")
      .extensions("hstore,pgcrypto")
      .build();

    container.start();
  }
}

The above will programmatically start a Postgres 13 docker container on port 6432. It will create a database and user with container name pg13x. It will drop and re-create the container if the container already exists.

Docker trace logging

Set the logging level for io.ebean.docker to trace to help trouble shoot any issues or understand what ebean-test-docker is doing.

PostGIS

To use PostGIS goto the PostGIS documentation.