1. Introduction

The Hibernate4 plugin enables lightweight access to datasources using Hibernate. This plugin does NOT provide domain classes nor dynamic finders like GORM does.

Griffon version: 2.12.0

2. Usage

The following sections describe how you may use this plugin in a project.

2.1. Configuration

This plugin relies on the griffon-datasource-plugin. Please follow the instructions to configure this plugin first.

You must create a configuration file named Hibernate4 that holds the settings for creating instances of SessionFactory. This file follows the same standard configuration mechanism as the application’s Config file, which means you can define the configuration using

  • a properties file

  • a Java file

  • a Groovy script

The following example shows the default settings needed to connect the default database taking into account that each environment may connect to a different database.

src/main/resources/Hibernate4.groovy
sessionFactory {

}

environments {
    development {
        sessionFactory {
        }
    }
    test {
        sessionFactory {
        }
    }
    production {
        sessionFactory {
        }
    }
}

You may configure multiple named SessionFactories (the default factory is aptly named default) as the following snippet shows

src/main/resources/Hibernate4.groovy
sessionFactories {
    internal {
        schema = 'create-drop'
    }
    people {
        schema = 'create-drop'
    }
}

2.1.1. Session Properties

The following table summarizes the properties that can be specified inside a sessionFactory block

Property Type Default Description

schema

String

create-drop

Any value accepted by "hibernate.hbm2ddl.auto"

logSql

boolean

false

Defines value for "hibernate.show_sql"

formatSql

boolean

false

Defines value for "hibernate.format_sql"

dialect

String or Class

Defines value for "hibernate.dialect"

entityInterceptor

String or Class

namingStrategy

String or Class

props

Properties or Map

mappings

List

Additional resource mappings

connect_on_startup

boolean

false

Establishes a connection to the datasource at the beginning of the Startup phase.

jmx

boolean

true

Expose the connection pool using JMX.

2.1.2. Accessing the Datasource

The plugin’s module registers a Hibernate4Handler helper class that defines the base contract for accessing a datasource and issue SQL queries to it. This class has the following methods

griffon.plugins.hibernate4.Hibernate4Handler.java
@Nullable
<R> R withHbm4Session(@Nonnull Hibernate4Callback<R> callback)
    throws RuntimeHibernate4Exception;

@Nullable
<R> R withHbm4Session(@Nonnull String sessionFactoryName, @Nonnull Hibernate4Callback<R> callback)
    throws RuntimeHibernate4Exception;

void closeHbm4Session();

void closeHbm4Session(@Nonnull String sessionFactoryName);

These method are aware of multiple datasources. If no sessionFactoryName is specified when calling them then the default datasource will be selected. You can inject an instance of this class anywhere it’s needed using @Inject. There is one callback you may use with this method: Hibernate4Callback.

This callback is defined using a functional interface approach, which means you can apply lambda expressions if running with JDK8+ or closures if running Groovy.

griffon.plugins.hibernate4.Hibernate4Callback.java
public interface Hibernate4Callback<R> {
    R handle(@Nonnull String sessionFactoryName, @Nonnull Session session);
}

2.1.3. Mappings

Hibernate requires mapping resources for matching classes to tables. The plugin can automatically discover mappings that should be added to a SessionFactory as long as they are annotated with @TypeProviderFor. For example

src/main/groovy/com/acme/Person.groovy
package griffon.plugins.hibernate4

import griffon.metadata.TypeProviderFor
import groovy.transform.ToString

@ToString
@TypeProviderFor(Hibernate4Mapping)
class Person implements Serializable, Hibernate4Mapping {
    int id
    String name
    String lastname

    Map asMap() {
        [
            id      : id,
            name    : name,
            lastname: lastname
        ]
    }
}

Don’t forget mappings require a matching XML file that contains query definitions, such as

src/main/resources/griffon/plugins/hibernate4/Person.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="griffon.plugins.hibernate4">
    <class name="Person" table="PEOPLE">
        <id name="id" column="PERSON_ID">
            <generator class="increment"/>
        </id>
        <property name="name" not-null="true"/>
        <property name="lastname" not-null="true"/>
    </class>
</hibernate-mapping>

2.1.4. Bootstrap

You may execute arbitrary database calls during connection and disconnection from a SessionFactory. Simply create a class that implements the Hibernate4Bootstrap interface and register it within a module, for example

src/main/java/com/acme/SampleHibernate4Bootstrap.java
package com.acme;

import griffon.plugins.hibernate4.Hibernate4Bootstrap;
import org.hibernate.Session;

import javax.annotation.Nonnull;
import javax.inject.Named;

@Named("sample")
public class SampleHibernate4Bootstrap implements Hibernate4Bootstrap {
    @Override
    public void init(@Nonnull String sessionFactoryName, @Nonnull Session session) {
        // operations after first connection to datasource
    }

    @Override
    public void destroy(@Nonnull String sessionFactoryName, @Nonnull Session session) {
        // operations before disconnecting from the datasource
    }
}
src/main/java/com/acme/ApplicationModule.java
package com.acme;

import griffon.plugins.hibernate4.Hibernate4Bootstrap;
import griffon.core.injection.Module;
import org.codehaus.griffon.runtime.core.injection.AbstractModule;
import org.kordamp.jipsy.ServiceProviderFor;

@ServiceProviderFor(Module.class)
public class ApplicationModule extends AbstractModule {
    @Override
    protected void doConfigure() {
        bind(Hibernate4Bootstrap.class)
            .to(SampleHibernate4Bootstrap.class)
            .asSingleton();
    }
}

2.2. Example

The following is a trivial usage of the Hibernate4Handler inside a Java service

com.acme.SampleService.java
package com.acme;

import griffon.core.artifact.GriffonService;
import griffon.metadata.ArtifactProviderFor;
import org.codehaus.griffon.runtime.core.artifact.AbstractGriffonService;

import griffon.plugins.hibernate4.Hibernate4Handler;
import griffon.plugins.hibernate4.Hibernate4Callback;
import org.hibernate.Session;

import javax.annotation.Nonnull;
import javax.inject.Inject;

@ArtifactProviderFor(GriffonService.class)
public class SampleService extends AbstractGriffonService {
    @Inject
    private Hibernate4Handler hibernate4Handler;

    public String getPersonName(final int id) {
         return hibernate4Handler.withHbm4Session(new Hibernate4Callback<String>() {
             public String handle(@Nonnull String sessionFactoryName, @Nonnull Session session) {
                 Person person = (Person) session.createQuery("from Person where id = " + id).uniqueResult();
                 return person != null ? person.getName() : null;
         });
    }
}

Here’s the Groovy version of it

com.acme.SampleService.groovy
package com.acme

import griffon.core.artifact.GriffonService
import griffon.metadata.ArtifactProviderFor

import griffon.plugins.hibernate4.Hibernate4Handler
import org.hibernate.Session

import javax.inject.Inject

@ArtifactProviderFor(GriffonService)
class SampleService {
    @Inject
    private Hibernate4Handler hibernate4Handler

    String getPersonName(int id) {
         hibernate4Handler.withHbm4Session { String sessionFactoryName, Session session ->
             session.createQuery('from Person where id = ' + id).uniqueResult()?.name
         }
    }
}

2.3. Events

The following events will be triggered by Hibernate4Handler

Hibernate4ConnectStart(String sessionFactoryName, Map<String, Object> config)

Triggered before connecting to the datasource.

Hibernate4ConfigurationAvailable(Map<String, Object> options)

Triggered after the session’s configuration is ready. The map contains the following keys:

  • configuration; type=org.hibernate.cfg.Configuration

  • dataSourceName; type=java.lang.String

  • sessionConfiguration; type=java.util.Map

Hibernate4ConnectEnd(String sessionFactoryName, Map<String, Object> config, SessionFactory factory)

Triggered after connecting to the datasource.

Hibernate4DisconnectStart(String sessionFactoryName, Map<String, Object> config, SessionFactory factory)

Triggered before disconnecting from the datasource.

Hibernate4DisconnectEnd(String sessionFactoryName, Map<String, Object> config)

Triggered after disconnecting from the datasource.

DataSource events may be triggered during connection and disconnection from a SessionFactory.

2.4. AST Transformation

You can apply the @Hibernate4Aware AST transformation on any class. This injects the behavior of Hibernate4Handler into said class. The previous Groovy service example can be rewritten as follows

com.acme.SampleService.groovy
package com.acme

import griffon.core.artifact.GriffonService
import griffon.metadata.ArtifactProviderFor
import griffon.transform.Hibernate4Aware

import org.hibernate.Session

@Hibernate4Aware
@ArtifactProviderFor(GriffonService)
class SampleService {
    String getPersonName(int id) {
         withHbm4Session { String sessionFactoryName, Session session ->
             session.createQuery('from Person where id = ' + id).uniqueResult()?.name
         }
    }
}

2.5. DSL Descriptors

This plugin provides DSL descriptors for Intellij IDEA and Eclipse (provided you have the Groovy Eclipse plugin installed). These descriptors are found inside the griffon-hibernate4-groovy-compile-2.1.0.jar, with locations

  • dsdl/griffon_hibernate4.dsld

  • gdsl/griffon_hibernate4.gdsl

3. Build Configuration

3.1. Gradle

You have two options for configuring this plugin: automatic and manual.

3.1.1. Automatic

As long as the project has the org.codehaus.griffon.griffon plugin applied to it you may include the following snippet in build.gradle

dependencies {
    griffon 'org.codehaus.griffon.plugins:griffon-hibernate4-plugin:2.1.0'
}

The griffon plugin will take care of the rest given its configuration.

3.1.2. Manual

You will need to configure any of the following blocks depending on your setup

dependencies {
    compile 'org.codehaus.griffon.plugins:griffon-hibernate4-core:2.1.0'
}
Compile Only
dependencies {
    compileOnly 'org.codehaus.griffon.plugins:griffon-hibernate4-groovy-compile:2.1.0'
}

3.2. Maven

First configure the griffon-hibernate4-plugin BOM in your POM file, by placing the following snippet before the <build> element

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.codehaus.griffon.plugins</groupId>
            <artifactId>griffon-hibernate4-plugin</artifactId>
            <version>2.1.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Next configure dependencies as required by your particular setup

<dependency>
    <groupId>org.codehaus.griffon.plugins</groupId>
    <artifactId>griffon-hibernate4-core</artifactId>
</dependency>
Provided scope
<dependency>
    <groupId>org.codehaus.griffon.plugins</groupId>
    <artifactId>griffon-hibernate4-groovy-compile</artifactId>
</dependency>

Don’t forget to configure all -compile dependencies with the maven-surefire-plugin, like so

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <classpathDependencyExcludes>
            <classpathDependencyExclude>
                org.codehaus.griffon:griffon-hibernate4-groovy-compile
            </classpathDependencyExclude>
        </classpathDependencyExcludes>
    </configuration>
</plugin>

4. Modules

The following sections display all bindings per module. Use this information to successfully override a binding on your own modules or to troubleshoot a module binding if the wrong type has been applied by the Griffon runtime.

4.1. Hibernate4

Module name: hibernate4

Depends on: datasource

bind(ResourceBundle.class)
    .withClassifier(named("hibernate4"))
    .toProvider(new ResourceBundleProvider("Hibernate4"))
    .asSingleton();

bind(Configuration.class)
    .withClassifier(named("hibernate4"))
    .to(DefaultHibernate4Configuration.class)
    .asSingleton();

bind(Hibernate4Storage.class)
    .to(DefaultHibernate4Storage.class)
    .asSingleton();

bind(Hibernate4Factory.class)
    .to(DefaultHibernate4Factory.class)
    .asSingleton();

bind(Hibernate4Handler.class)
    .to(DefaultHibernate4Handler.class)
    .asSingleton();

bind(GriffonAddon.class)
    .to(Hibernate4Addon.class)
    .asSingleton();