Red Hat

In Relation To Hibernate ORM

In Relation To Hibernate ORM

Hibernate ORM 5.0 has gone Final!

Posted by Steve Ebersole    |       |    Tagged as Hibernate ORM Releases

Today I have released Hibernate ORM 5.0 (5.0.0.Final). This has been a long time coming and is the result of the efforts of many folks. Thanks to everyone who helped us get here with fixes, bug reports, suggestions, input and encouragement!

A lot of development has gone into 5.0. Here are the big points:

New bootstrap API

The venerable way to bootstrap Hibernate (build a SessionFactory) has been to use its Configuration class. Configuration, historically, allowed users to iteratively add settings and mappings in any order and to query the state of settings and mapping information in the middle of that process. Which meant that building the mapping information could not effectively rely on any settings being available. This lead to many limitations and problems.

5.0 introduces a new bootstrapping API aimed at alleviating those limitations and problems, while allowing better determinism and better integration. See the Bootstrap chapter in the User Guide for details on using the new API.

Configuration is still available for use, although in a limited sense. Some of its methods have been removed. Under the covers Configuration makes use of the new bootstrap API.

Spatial/GIS support

Hibernate Spatial is a project that has been around for a number of years. Karel Maesen has done an amazing job with it.

Starting in 5.0 Hibernate Spatial is now part of the Hibernate project proper to allow it to better keep up with upstream development. It is available as org.hibernate:hibernate-spatial. If your appplication has need for GIS data, we highly recommend giving hibernate-spatial a try.

Java 8 support

Well, ok.. not all of Java 8. Specifically we have added support for Java 8 Date and Time API in regards to easily mapping attributes in your domain model using the Java 8 Date and Time API types to the database. This support is available under the dedicated hibernate-java8 artifact (to isolate Java 8 dependencies). For additional information, see the Basic Types chapter in the Domain Model Mapping Guide.

Expanded AUTO id generation support

JPA defines support for GenerationType#AUTO limited to just Number types. Starting in 5.0 Hibernate offers expandable support for a broader set of types, including built-in support for both Number types (Integer, Long, etc) and UUID. Users are also free to plug in custom strategies for interpreting GenerationType#AUTO via the new org.hibernate.boot.model.IdGeneratorStrategyInterpreter extension.

Naming strategy split

NamingStrategy has been removed in favor of a better designed API. 2 distinct ones actually:

  • org.hibernate.boot.model.naming.ImplicitNamingStrategy - used whenever a table or column is not explicitly named to determine the name to use

  • org.hibernate.boot.model.naming.PhysicalNamingStrategy - used to convert a "logical name" (either implicit or explicit) name of a table or column into a physical name (e.g. following corporate naming guidelines)

Attribute Converter support

5.0 offers significantly improved support for JPA 2.1 AttributeConverters:

  • fully supported for non-@Enumerated enum values

  • applicable in conjunction with @Nationalized support

  • now called to handle null values

  • settable in hbm.xml by using type="converter:fully.qualified.AttributeConverterName"

  • integrated with hibernate-envers

  • collection values, map keys

  • support for conversion of parameterized types

Better "bulk id table" support

Support for "bulk id tables" has been completely redesigned to better fit what different databases support.

Transaction management

The transaction SPI underwent a major redesign as part of 5.0 as well. From a user perspective this generally only comes into view in terms of configuration. Previously applications would work with the different backend transaction stratagies directly via the org.hibernate.Transaction API. In 5.0 a level of indirection has been added here. The API implementation of org.hibernate.Transaction is always the same now. On the backend, the org.hibernate.Transaction impl talks to a org.hibernate.resource.transaction.TransactionCoordinator which represents the "transactional context" for a given Session according to the backend transaction strategy. Users generally do not need to care about the distinction.

The change is noted here because it might affect your bootstrap configuration. Whereas previously applications would specify hibernate.transaction.factory_class and refer to a org.hibernate.engine.transaction.spi.TransactionFactory FQN, with 5.0 the new contract is org.hibernate.resource.transaction.TransactionCoordinatorBuilder and is specified using the hibernate.transaction.coordinator_class setting. See org.hibernate.cfg.AvailableSettings.TRANSACTION_COORDINATOR_STRATEGY JavaDocs for additional details.

The following short-names are recognized: jdbc::(the default) says to use JDBC-based transactions (org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl) jta::says to use JTA-based transactions (org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl)

See the User Guide for additional details.

Schema Tooling

5.0 offers much improvement in the area of schema tooling (export, validation and migration).

Typed Session API

Hibernate’s native APIs (Session, etc) have been updated to be typed. No more casting!

Improved OSGi support

Really this started with a frustration over the fragility of hibernate-osgi tests. The first piece was a better testing setup using Pax Exam and Karaf. This lead to us generating (and now publishing!) a Hibernate Karaf features file.

OSGi support has undergone some general improvement as well thanks to feedback from some Karaf and Pax developers and users.

See the Getting Started Guide for additional details on using the new Karaf features file.

Improved bytecode enhancement capabilities

Work on documentation

A lot of work has gone into the documentation for 5.0. It’s still not complete (is documentation ever "complete"?), but it is much improved.

See the revamped documentation page for details.

BinTray

For now the plan is to publish the release bundles (zip and tgz) to BinTray. We will continue to publish to SourceForge as well. For the time being we will publish the bundles to both.

Ultimately we will start to publish the "maven" artifacts there as well.

This is all a work in progress.

How to get it

See http://hibernate.atlassian.net/projects/HHH/versions/20851 for the complete list of changes.

See http://hibernate.org/orm/downloads/ for information on obtaining the releases.

Hibernate ORM 4.2.20.Final was released 24-July-2015. At the time it was released, SourceForge was out of commission so distributions could not be uploaded. I decided to delay the announcement until SourceForge was back in commission and I was able to release 4.3.11.Final on 5-Aug-2015.

Notable bugfixes

In both 4.3.11.Final and 4.2.20.Final:

  • HHH-2851 fixed a longstanding bug affecting dialects that require the type for binding null parameter values to a query predicate like (:param IS NULL OR alias.someField = :param). This bug affected Oracle and SQL Server dialects, and possibly others. This bug was easily worked around, but it was clearly a headache for people using those dialects.

In 4.3.11.Final only:

  • HHH-9287 fixed a bug that caused pooled optimizer identifiers to be reused if an external (to Hibernate) system inserted a row using the same sequence.

  • Hibernate’s support for AttributeConverter was improved. HHH-8804 adds support for a parameterized type as an AttributeConverter type parameter (e.g., AttributeConverter<Set<Category>, String>); HHH-8854 fixed a bug extracting the ParameterizedType representation of AttributeConverter definition from an implementation that did not directly implement AttributeConverter i.e., a superclass implements AttributeConverter.

  • There were some bugfixes related to lazy (byte-code instrumented) properties. HHH-5255 fixed a longstanding bug merging a detached entity with a lazy property that has been initialized (this only works for "property" access); HHH-7573 fixed a bug processing lazy properties after an EntityManager PreUpdate callback; HHH-9629 fixed a bug in cache key generation for an entity with inheritance when fetching lazy property.

How to get it

Fourth Candidate Release for ORM 5.0

Posted by Steve Ebersole    |       |    Tagged as Hibernate ORM Releases

Today I released a fourth candidate release for Hibernate ORM 5.0 (5.0.0.CR4). The purpose was entirely to change the defaults for some settings. This allowed some additional fixes and additional documentation work to make it in.

Default ImplicitNamingStrategy

The default ImplicitNamingStrategy (hibernate.implicit_naming_strategy) has changed to the JPA-compliant one. Additionally I added some short-names for the Hibernate-provided implementations.

  • "default" → org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl

  • "jpa" → org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl

  • "legacy-jpa" → org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl

  • "legacy-hbm" → org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl

  • "component-path" → org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl

The previous default was "legacy-jpa". Existing applications that previously used the default naming strategy and want to continue to use that implicit naming strategy should specify hibernate.implicit_naming_strategy=legacy-jpa in their configuration settings. Alternatively, they can call MetadataBuilder#setImplicitNamingStrategy(ImplicitNamingStrategyLegacyJpaImpl.INSTANCE).

Identifier generator mapping

Back in 3.6 I developed a new set of identifier generator strategies aimed at database portability based on the JPA expectations for @SequenceGenerator and @TableGenerator. Between 3.6 and now the default has been to continue to use the legacy generator strategies, but we added a setting (hibernate.id.new_generator_mappings) to allow applications to request the newer strategies be used. The default for this setting had been false. The default is now true.

Existing applications updating to CR4 and then Final that experience issues with identifier generator strategy selection should try setting this back to false if they wish to keep using the legacy mappings.

Keyword auto-quoting

This is a new feature in 5.0, but previously the default had been to auto-quote any sql identifiers believed to be a keyword in the underlying database. That feature has been disabled by default.

Applications that wish to use this feature should explicitly enable it by specifying hibernate.auto_quote_keyword=true in their configuration settings.

More work on the documentation

Still in progress, but alot more content has been added.

How to get it

Additionally many other improvements and bugfixes are included. See https://hibernate.atlassian.net/projects/HHH/versions/20752 for the complete list of changes.

As always, see http://hibernate.org/orm/downloads/ for information on obtaining the releases.

Third Candidate Release for ORM 5.0

Posted by Steve Ebersole    |       |    Tagged as Hibernate ORM Releases

Yesterday I released the third candidate release for Hibernate ORM 5.0 (5.0.0.CR3). We felt another CR was warranted because we had some minor integration (SPI) work that we needed to make in to Final, but too much development had happened since the second CR to be considered risk free to just include everything into Final. At any rate CR3 got lots of great TLC :) The complete set of changes can be seen in the Jira changelog. The main changes include:

Minor changes to the caching SPI

Essentially passing Session along to the various region access strategy methods to allow integrating with non-JDBC transactions.

Work on schema tooling

Improved namespace (catalog/schema) support overall in schema tools. Improved handling of views and synonyms for migrating and validating.

Work on bytecode enhancement

Lots of fixes based on feedback.

Consistency in Transaction API

A few changes were made to the JDCB-based TransactionCoordinator to work more like in JTA environments. Specifically:

  • implemented support for marking the Transaction for rollback-only.

  • transaction is now rolled back automatically on a failed commit.

Work on the documentation

Besides updating the content, the content has been split into 3 separate guides:

  • User Guide

  • Domain Model Mapping Guide

  • Integrations Guide

How to get it

Additionally many other improvements and bugfixes are included. See https://hibernate.atlassian.net/projects/HHH/versions/20150 for the complete list of changes.

As always, see http://hibernate.org/orm/downloads/ for information on obtaining the releases.

Map me if you can - Advanced embeddable mappings

Posted by Gunnar Morling    |       |    Tagged as Hibernate ORM

The other day I came across an interesting mapping challenge which I thought may be worth sharing. If you are a seasoned JPA user, it will probably be nothing new to you, but those not as experienced may find it helpful :)

TL;DR - JPA let’s you override database columns for embedded objects but also for collections of embedded objects; @AttributeOverride and @AssocationOverride can be used for that.

Let’s assume the following entity model representing a person and their home and business address:

Entity model

The interesting part is that Person has two associations with Address, one with the "homeAddress" role and another one with the "businessAddress" role. Address in turn has one ore more address lines.

When mapping these types with JPA, Person naturally becomes an entity. As there is a composition relationship between Person and Address, the latter is mapped with @Embeddable. The same goes for AddressLine, which also is an @Embeddable, contained within an element collection owned by Address.

So you’d end up with these classes:

@Entity
public class Person {

    @Id
    private long id;
    private String name;
    private Address homeAddress;
    private Address businessAddress;

    // constructor, getters and setters...
}
@Embeddable
public class Address {

    private boolean active;

    @ElementCollection
    private List<AddressLine> lines = new ArrayList<AddressLine>();

    // constructor, getters and setters...
}
@Embeddable
public class AddressLine {

    private String value;

    // constructor, getters and setters...
}

@AttributeOverride

Let’s fire up a session factory with these types (this uses the brand-new bootstrapping API coming in Hibernate ORM 5) and see how that goes:

StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
    .applySetting( AvailableSettings.SHOW_SQL, true )
    .applySetting( AvailableSettings.FORMAT_SQL, true )
    .applySetting( AvailableSettings.HBM2DDL_AUTO, "create-drop" )
    .build();

SessionFactory sessionFactory = new MetadataSources( registry )
    .addAnnotatedClass( Person.class )
    .buildMetadata()
    .buildSessionFactory();

Hum, that did not go too well:

org.hibernate.MappingException: Repeated column in mapping for entity:
org.hibernate.bugs.Person column: active (should be mapped with insert="false" update="false")

Of course this makes sense; As Address is embedded twice within Person, its properties must be mapped to unique column names within the Person table. The @AttributeOverride annotation can be used for that:

@Entity
public class Person {

    @Id
    private long id;
    private String name;

    @AttributeOverride(name = "active", column = @Column(name = "home_address_active"))
    private Address homeAddress;

    @AttributeOverride(name = "active", column = @Column(name = "business_address_active"))
    private Address businessAddress;

    // constructor, getters and setters...
}

With that, the session factory boots successfully. But let’s take a look at the tables that get created:

create table Person (
    id bigint not null,
    business_address_active boolean,
    home_address_active boolean,
    name varchar(255),
    primary key (id)
)

create table Person_lines (
    Person_id bigint not null,
    "value" varchar(255)
)

@AssociationOverride

The Person table looks alright, but there is only a single table for the address lines. That’s a problem as it means there is no way to tell apart the lines of the business address from the lines of the home address when reading back a person from the database.

So what to do? @AttributeOverride is of no help this time, as it’s not a single column which needs to be re-defined but an entire table. But luckily, @AttributeOverride has a companion, @AssociationOverride. This annotation can be used to configure the required tables in this case:

@Entity
public class Person {

    @Id
    private long id;
    private String name;

    @AttributeOverride(name = "active", column = @Column(name = "home_address_active"))
    @AssociationOverride(name = "lines", joinTable = @JoinTable(name = "Person_HomeAddress_Line"))
    private Address homeAddress;

    @AttributeOverride(name = "active", column = @Column(name = "business_address_active"))
    @AssociationOverride(name = "lines", joinTable = @JoinTable(name = "Person_BusinessAddress_Line"))
    private Address businessAddress;

    // constructor, getters and setters...
}

Et voilĂ , now you’ll get the DDL for creating the Person table and two different tables for the address lines:

create table Person (
    id bigint not null,
    business_address_active boolean,
    home_address_active boolean,
    name varchar(255),
    primary key (id)
)

create table Person_BusinessAddress_Line (
    Person_id bigint not null,
    "value" varchar(255)
)

create table Person_HomeAddress_Line (
    Person_id bigint not null,
    "value" varchar(255)
)

IntelliJ IDEA, Mac OS X and Hibernate ORM

Posted by Emmanuel Bernard    |       |    Tagged as Hibernate ORM

Hibernate ORM, IntelliJ IDEA and Mac OS X have been a pretty tough combination to work with since our move to Gradle. It’s not exactly anyone’s fault but the combination of

  • gradle / IntelliJ integration

  • JDK 6 running IntelliJ IDEA

  • Hibernate ORM advanced use of Gradle and of custom plugins

made for a long and painful journey.

These days are over. Steve found the last blocking issue and you can now import Hibernate ORM natively in IntelliJ IDEA.

Importing Hibernate ORM in IntelliJ IDEA on Mac OS X

git clone git@github.com:hibernate/hibernate-orm.git
  • Open IntelliJ IDEA

  • File → Open

  • Select hibernate-orm

  • The defaults should be good

    • Make especially sure that you select Use default gradle wrapper

    • I use Gradle JVM to 1.8

  • Click OK and let it work and download the internet

You now have a properly imported Hibernate ORM project :)

This worked on Mac OS X 10.10.4 and IntelliJ IDEA CE 14.1.4.

Importing Hibernate ORM in NetBeans on Mac OS X

And this incidentally fixed an import bug for NetBeans.

  • Open NetBeans

  • Install the Gradle plugin

  • Open project

  • Select hibernate-orm

This worked on Mac OS X 10.10.4 and NetBeans 8.0.2.

Second Candidate Release for 5.0

Posted by Steve Ebersole    |       |    Tagged as Hibernate ORM Releases

The second candidate release for Hibernate ORM 5.0. CR2 was required because of a bug in how class-loading worked in certain managed JPA environments. The details can be found in HHH-9887. The main changes since CR1 include:

Corrected ClassLoader usage

This is the blocking issue mentioned above. The problem would occur in environments passing a "temp ClassLoader" into Hibernate via the JPA integration SPI (javax.persistence.spi.PersistenceUnitInfo#getNewTempClassLoader) and manifest itself as ClassCastExceptions.

Second-level caching SPI improvement

The second-level caching SPI was improved, allowing the caching providers to generate cache keys. This includes the addition of the following methods:

  • org.hibernate.cache.spi.access.EntityRegionAccessStrategy#generateCacheKey

  • org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#generateCacheKey

  • org.hibernate.cache.spi.access.NaturalIdRegionAccessStrategy#generateCacheKey

Improved cache-by-reference support

For those making use of caching immutable entities by reference (rather than by "disassembled" state), an additional performance improvement is included in CR2.

Ability to disable auto-quoting of keyword-as-identifier

A new feature in 5.0 is the automatic quoting of identifiers that are believed to be keywords in the underlying database. As this support is new, often the Dialects are too aggressive in what they deem to be keywords. Thus we added a new setting to disable this behavior if it causes problems in your application. This can be controlled by specifying hibernate.auto_quote_keyword as false in configuration settings.

Significantly improved bytecode enhancement support

Including:

  • added ability for automatic management of bi-directional associations

  • self-contained dirty state tracking (more efficient flushing), including switchable algorithms for dirty determination

Odds-n-ends

Additionally many other improvements and bugfixes are included. See the changelogs for the complete list of changes.

The release tag is available on GitHub.

As always, see http://hibernate.org/orm/downloads/ for information on obtaining the releases.

Multitenancy and current session

Posted by Emmanuel Bernard    |       |    Tagged as Hibernate ORM

Today let’s discuss the interaction between multitenancy and the current session feature.

Multitenancy let’s you isolate Session operations between different tenants. This is useful to create a single application isolating different customers from one another.

The current session feature returns the same session for a given context, typically a (JTA) transaction. This facilitates the one session per view/transaction/conversation pattern and avoids the one session per operation anti-pattern.

Session session = sessionFactory.getCurrentSession();
// do some other work
[...]
// later in the same context (e.g. JTA Transaction)
Session session2 = sessionFactory.getCurrentSession();

// semantically we have
assert session == session2

The two features work well together, simply implement CurrentTenantIdentifierResolver. That will give Hibernate ORM the expected tenant id when the current session is created.

How current is current?

When discussing with Florian and the ToulouseJUG, we exchanged on a small case where things might not work as you expect. Hibernate ORM considers that, for a given context (e.g. transaction), there can only be a single current Session.

So if in the same context (e.g. transaction):

  • your CurrentTenantIdentifierResolver implementation returns different values of tenant id,

  • you use getCurrentSession()

you will get a TenantIdentifierMismatchException.

However, it is sometimes useful to be able to reach several tenants from the same context. You have two options:

  • Manually create the Session

  • Implement a custom CurrentSessionContext

Manually create the Session

You can use the SessionFactory API to create a Session for the tenant id you are looking for.

Session session1 = sessionFactory.withOptions()
        .tenantIdentifier( tenant1 )
        ...
        .openSession();
Session session2 = sessionFactory.withOptions()
        .tenantIdentifier( tenant2 )
        ...
        .openSession();

But you have to make sure to close these sessions. If you are used to CDI or Spring handling sessions for you, or if you rely on the current session feature to propagate the session across your stack, this might be annoying.

Implement a custom CurrentSessionContext

The alternative is to implement your own version of CurrentSessionContext, avoid raising the TenantIdentifierMismatchException, and keep Session instances per both context and tenant id.

In practice, current sessions are stored in a ConcurrentHashMap keyed by context identifier, you just need to improve that part. Start with JTASessionContext and hack away!

What now?

We are currently discussing whether the default CurrentSessionContext implementations should partition by tenant id or raise the exception. If you have your opinion, chime in!

In the mean time, use one of the options above.

When creating a bug report for any project within the Hibernate family, it’s extremely helpful (and, frankly, required) to have an adequate test case available. This is obviously important to make reproducing the issue as easy as possible. But it’s also vital longer-term. Nearly every bug fix should include a regression test, which is frequently based on the original reproducer (sometimes, it’s the reproducer, verbatim).

To help create useful test cases, we’re opening up a repo with various templates. Please see the READMEs in each project’s subdir for more info: Hibernate Test Case Templates

As a starting point, the repo contains two templates for ORM:

  • ORMUnitTestCase: By far, this one’s the most helpful. ORM includes a built-in unit test framework that does much of the heavy lifting for you. All that’s required is your entities, logic, and any necessary settings. Since we nearly always include a regression test with bug fixes, providing your reproducer using this method simplifies the process. We can then directly commit it, without having to mold it in first. What’s even better? Fork hibernate-orm itself, add your test case directly to a module’s unit tests (using the template class), then submit it as a PR!

  • ORMStandaloneTestCase: This template is standalone and will look familiar. It simply uses a run-of-the-mill ORM setup. Although it’s perfectly acceptable as a reproducer, lean towards ORMUnitTestCase whenever possible.

The eventual goal is to also include templates for Validator, Search, and OGM.

As always, this is open source for a reason! If the templates can be improved in any way, please let us know (either through our JIRA instance or through GitHub Issues). Better yet, send us a pull request!

For those of you using Hibernate ORM version 5.0.0.CR1, you can now use the freshly released Hibernate Search 5.4 version 5.4.0.Alpha1.

What's new

Absolutely nothing! This Hibernate Search version is identical in terms of features and API to version 5.3.0.CR1: this should make it easier for you all to upgrade the Hibernate ORM libraries (hibernate-core, hibernate-entitymanager,..) without the distraction of changes because of Hibernate Search: focus on the changes you'll need to apply because of the major version upgrade of Hibernate (if any, as it's not too complex at all).

WildFly compatibility and JBoss Modules

With every release of Hibernate Search we normally also release a set of modules to run the latest version of it on WildFly, but in this case since the updated Hibernate ORM 5 integrations for WildFly have yet to be released, we skipped this step. Fear not, the WildFly integration will be finished soon and we'll then resume releasing such module packs as usual. Not least, this very same version of Hibernate Search will soon be available in WildFly 10, so the modules missing today won't actually be needed at all.

This is a great time to try Hibernate 5

While the latest polish is performed on Hibernate 5, we're all looking forward for feedback from you. It is likely that some more changes will be done, but we consider it good enough already to not expect any regression so please try it and let us know! We're at that sweet spot in which you can still propose changes without the chains of strong API compatibility requirements, but good enough for you to not be wasting time on a quickly changing target.

Versions reminder

This version of Hibernate Search requires:

  • Hibernate ORM 5.0.0.CR1
  • Apache Lucene 4.10.x
  • Java SE 7

Our rules and conventions for versions and compatibility are documented here on the GitHub Wiki.

  • Artefact jars are available on Maven Central under the GAV org.hibernate:hibernate-search-orm:5.4.0.Alpha1
  • Zip and tar bundles are available via our website
  • Feedback is welcome on the forums and emails, IRC
back to top