Skip to content

JPA Support

John Ament edited this page Jan 2, 2018 · 10 revisions

JPA Support with Hammock

JPA is supported out of the box with Hammock, allowing you to leverage the built in functions as well as some custom grown features.

Creating DataSources

Before we get into JPA, its important to understand how configuration of DataSources works. There are a few ways to create DataSources using Hammock. Hammock does provide support for @DataSourceDefinition and @DataSourceDefinitions found on any CDI managed bean. However, a producer method is probably the cleaner way since it allows the configuration to be externalized. Such a bean may look like this:

@Inject
@ConfigProperty(name="test2.url")
private String url;

@Inject
@ConfigProperty(name="test2.username")
private String username;

@Inject
@ConfigProperty(name = "test2.password")
private String password;

@Produces
@ApplicationScoped
@Database("test2")
public DataSourceDefinition createDataSource(DataSourceDefinitionBuilder builder) {
   return builder.url(url)
      .user(username)
      .password(password)
      .name("test2")
      .build();
}

Default Persistence unit

Hammock by default creates a default persistence unit for your app, and unless you need something special its probably the right way to go. The unit is named __default and it works by finding all entities defined within your application, pointing to the datasource defined by the name in hammock.jpa.__default.datasource. All custom properties that are prefixed by hammock.jpa.__default will get added to the EntityManagerFactory on creation, allowing you to override additional configuration via properties.

The name of the default persistence unit can be changed using hammock.default.persistence.unit.name. This affects all properties as well.

Overriding the Default Persistence Unit

Most of the configuration of the default persistence unit can be done via configuration and with sensible defaults. However, there are some cases where you just need to have a representation of the XML file available, but in Java code. This gives you finer grained control over the definition of your JPA runtime. You can create a custom Producer method that creates a PersistenceUnitInfo bean for you

@ApplicationScoped
public class PUConfiguration {
    @Produces
    @Database("__default")
    public PersistenceUnitInfo createPU(PersistenceUnitBuilder builder, DataSourceDefinitionBuilder dataSourceDefinitionBuilder) {
        DataSourceDefinition dataSourceDefinition = dataSourceDefinitionBuilder.url("jdbc:h2:mem:another").build();
        return builder.withDataSource(dataSourceDefinition.getDataSource())
                .withProperty("javax.persistence.schema-generation.database.action", "drop-and-create")
                .withName("__default")
                .withClasses(Employee.class.getName())
                .build();
    }
}

This is copied from PUConfiguration. The name here will override the default __default persistence unit and replace the injection points with this one. You'll also note that this requires building the datasource definition as well (if you can't inject it via name). If you want to replace the built in support for HikariCP, you can use this approach as well since the PersistenceUnitBuilder only requires a DataSource and not a HammockDataSource.

Injection via @PersistenceContext and @PersistenceUnit

Injection of EntityManager and EntityManagerFactory via @PersitenceContext and @PersistenceUnit is available as a Weld specific extension that injects these components into any CDI managed bean. These objects can only be read from persistence.xml and will be mapped using the values specified in there only. DataSource integration is not available for these injection points. This is not a recommended approach

Creating custom Persistence Units

Hammock allows you to dynamically register a Persistence Unit within your application. This can be done using a PersistenceUnitBuilder and the underlying PersistenceProvider from your JPA implementation.

PersistenceUnitInfo persistenceUnitInfo = builder
   .withClasses(yourClasses)
   .withDataSource(dataSource)
   .loadAllProperties("some.prefix",true)
   .build();
PersistenceProvider provider = this.persistenceProvider;
EntityManagerFactory emf = provider.createContainerEntityManagerFactory(persistenceUnitInfo, emptyMap());

This EntityManagerFactory should be provided as a CDI bean. Likewise, Hammock will automatically detect any beans registered as PersistenceUnitInfo to make them eligible as a @Database EntityManager, where the value is the PersistenceUnit's name.

Persistence Providers

As of the 0.5.0 release, Hammock provides integration for three persistence providers. These coordinates are purely for bringing in the dependency and jpa-core. There is no code for any of these providers, they are all built against the JPA Specification

Group ID Artifact Id Description
ws.ament.hammock jpa-hibernate JPA Support with Hibernate 5.2.5
ws.ament.hammock jpa-openjpa JPA Support with Apache OpenJPA 2.4.1 (JPA 2.0 specification)
ws.ament.hammock jpa-eclipselink JPA Support with EclipseLink 2.6.0