Hibernate Devoxx 2022 talk

During Devoxx 2022 in Belgium I attended the Hibernate talk ORM, 20 years later by Mr. King, on of the founders of Hibernate. The first version of Hibernate was released at 23 May 2001.

My first encounter with Hibernate was in 2002 at my first job at Compuware. I worked from 2002 to 2007 on a code genaration tool OptimalJ that created initially a 3 tier (client / businesslogic / database) application using EJBs, Hibernate allowed us to skip the EJB layer and generate a more lightweight 3-tier application. The idea was that customers did not need to know the EJB 2.x overhead (which was quite a lot compared to the current EJB 3.x). We used Hibernate version 1.x with Data Access Objects at that time as an alternative to EJBs.

The Devoxx talk by Mr. King is not the best talk about Hibernate, but it sure mentions a lot of pain points Hibernate and later JPA encountered. One of the pain points I remember well is the complexity of the EntityManager usage and all the little things you kneed to know, especially in a distributed environment.

I was pleasantly suprised by the new Hibernate 6 release goals that are discussed in this talk. Very interesting to see how Mr. King his vision has changed over time.

Hibernate Stateless Session Test

In the video at

  • #2 at 06:00 - Hibernate and JPA were designed to work well in combination with handwritten SQL
  • #6 at 16:40 - People believe that they always need a DAO layer with ORM

Mr. King pointed out that one item that is not well known is that you do not need to use Entity mappings in Hibernate. You can also perform your own sql queries directly, while still enjoying the transaction logic Hibernate presents by using a StatelessSession. This can be useful when you know the exact optimized query you want to perform, and also useful for constructing objects that are not managed by Hibernate.

I wanted to try this out as a small exercise. You can find the results of my small test here: https://github.com/escay/demo-applications/tree/main/hibernate-stateless-session

Short version for insert and select:

    sessionFactory = MyHibernateUtil.createSessionFactory();
    session = sessionFactory.openStatelessSession();
    
    // Create table and insert record
    session.getTransaction().begin();
    session.createNativeMutationQuery("""
            CREATE TABLE persons (
                    id int,
                    first_name varchar(255),
                    last_name varchar(255)
            );""").executeUpdate();
    session.createNativeMutationQuery("INSERT INTO persons (id, first_name, last_name) VALUES (5, 'Tom', 'Erichsen');").executeUpdate();
    session.createNativeMutationQuery("INSERT INTO persons (id, first_name, last_name) VALUES (8, 'Ben', 'Johanssen');").executeUpdate();
    session.getTransaction().commit();

    // Test a query without a transaction   
    List<PersonRecord> persons = session.createNativeQuery("SELECT id, first_name, last_name FROM persons ORDER BY id", Tuple.class)
            .addScalar("id", StandardBasicTypes.INTEGER)
            .addScalar("first_name", StandardBasicTypes.STRING)
            .addScalar("last_name", StandardBasicTypes.STRING)
            .setTupleTransformer((tuples, aliases) -> {
                return new PersonRecord((int) tuples[0], (String) tuples[1], (String) tuples[2]);
            }).list();
    // Expect 2 rows
    assertEquals(2, persons.size());
    // Validate the first row
    PersonRecord firstResult = persons.get(0);
    assertEquals(5, firstResult.id());
    assertEquals("Tom", firstResult.firstName());
    assertEquals("Erichsen", firstResult.lastName());

See github for the full example.

During the creation of the example I ran into a deprecated method which I tried to replace, which resulted in unexpected / not documented behaviour.

Deprecated method:

session.createNativeQuery("SELECT id, name FROM persons ORDER BY id")

I expected to solve this using:

session.createNativeQuery("SELECT id, name FROM persons ORDER BY id", Object[].class)

But in the end it seems I must use:

session.createNativeQuery("SELECT id, name FROM persons ORDER BY id", Tuple.class)

I created an issue to improve the documentation and log why I think the code goes wrong: https://hibernate.atlassian.net/browse/HHH-15914

Update: HHH-15914 is fixed and Object[].class can be used again if desired.