Skip to content

SDA Commons Server Hibernate

javadoc

The module sda-commons-server-hibernate provides access to relational databases with hibernate. It is primarily designed to use PostgreSQL in production and H2 in memory in tests.

It provides - configuration of the database to use, - db migration using Flyway, - a health check for the database connection

sda-commons-server-hibernate ships with org.postgresql:postgresql, org.flywaydb:flyway-core and org.flywaydb:flyway-database-postgresql at compile scope.

Usage

Initialization

The HibernateBundle should be added as field in the application class instead of being anonymously added in the initialize method like other bundles of this library. Implementations need to refer to the instance to get access to the SessionFactory.

The Dropwizard applications config class needs to provide a DataSourceFactory.

The bundle builder requires to define the getter of the DataSourceFactory as method reference to access the configuration. One or more packages that should be scanned for entity classes must be defined.

Entity classes should be described using JPA annotations. The packages to scan may be either added as String or can be derived from a class or marker interface in the root of the model packages.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class MyApplication extends Application<MyConfiguration> {

   private final HibernateBundle<HibernateITestConfiguration> hibernateBundle = HibernateBundle.builder()
                          .withConfigurationProvider(MyConfiguration::getDatabase)
                          .withEntityScanPackageClass(MyEntity.class)
                          .build();

   // ...

}

In the context of a CDI application, the SessionFactory instance that is created in the HibernateBundle should be provided as CDI bean, so it can be injected into managers, repositories or however the data access objects are named in the application:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
@ApplicationScoped
public class MyCdiApplication extends Application<MyConfiguration> {

   private final HibernateBundle<HibernateITestConfiguration> hibernateBundle = HibernateBundle.builder()
                          .withConfigurationProvider(MyConfiguration::getDatabase)
                          .withEntityScanPackageClass(MyEntity.class)
                          .build();

   public static void main(final String[] args) throws Exception {
      // from sda-commons-server-weld
      DropwizardWeldHelper.run(SolutionServiceApplication.class, args);
   }

   // ...

   @jakarta.enterprise.inject.Produces
   public SessionFactory sessionFactory() {
      return hibernateBundle.sessionFactory();
   }

}
1
2
3
4
5
6
7
8
9
public class MyEntityManager extends io.dropwizard.hibernate.AbstractDAO<MyEntity> {

   @Inject
   public MyEntityManager(SessionFactory sessionFactory) {
      super(sessionFactory);
   }

   // ....
}

Configuration

The database connection is configured in the config.yaml of the application. It uses the format of Dropwizard Hibernate. Defaults are defined for PostgreSQL. The default PostgreSQL schema is public. The key (database in the examples) depends on the applications configuration class.

Example config for production:

1
2
3
4
database:
  user: username
  password: s3cr3t
  url: jdbc:postgresql://postgres-host:5432/my_service

Example config for developer machines using local-infra:

1
2
3
4
5
6
database:
  user: dbuser
  password: sda123
  url: jdbc:postgresql://localhost:5435/postgres
  properties:
    currentSchema: my_service

Example config for testing:

1
2
3
4
5
6
7
database:
  driverClass: org.h2.Driver
  user: sa
  password: sa
  url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
  properties:
    hibernate.dialect: org.hibernate.dialect.H2Dialect

Database access

DAOs or repositories are built by extending the AbstractDAO. The Dropwizard Hibernate Documentation has an example. The required SessionFactory is provided by the HibernateBundle instance.

Schema migration

For database schema migration, Flyway is used by the DbMigrationService and works with the same DataSourceFactory as the HibernateBundle. It may be used in a custom ConfiguredCommand in each application. Therefore, defaults for the command name and the documentation is provided:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class DbMigrationCommand extends ConfiguredCommand<MyAppConfig> {

   public DbMigrationCommand() {
      super(DbMigrationService.DEFAULT_COMMAND_NAME, DbMigrationService.DEFAULT_COMMAND_DOC);
   }

   @Override
   protected void run(Bootstrap<MyAppConfig> bootstrap, Namespace namespace, MyAppConfig configuration) {
      new DbMigrationService(configuration.getDatabase()).migrateDatabase();
   }
}

The command needs to be added to the application:

1
2
3
4
5
6
7
8
9
public class HibernateApp extends Application<MyAppConfig> {
   @Override
   public void initialize(Bootstrap<MyAppConfig> bootstrap) {
      // ...
      bootstrap.addCommand(new DbMigrationCommand());
      // ...
   }
   // ...
}

The command is then executed from command line to migrate the database:

1
java -jar my-application.jar migrateDB ./config.yaml

DB migration scripts are expected in src/main/resources/db.migration/*.sql.

Health check

A health check with the name hibernate is automatically registered to test the connection to the database. By default SELECT 1 is used as test query. It can be customized in the config.yaml:

1
2
database:
  validationQuery: SELECT 2

Testing

For testing database access with Hibernate we suggest to use sda-commons-hibernate-testing module.

Dependencies to be added:

1
    testCompile 'org.sdase.commons:sda-commons-server-hibernate-testing:<VERSION>'

For creating tests without a Dropwizard application please refer to the DbMigrationServiceTest as example.

For creating full integration tests of a Dropwizard application please refer to HibernateIT as example.