Red Hat

In Relation To Vlad Mihalcea

In Relation To Vlad Mihalcea

This article is about the HHH-11262 JIRA issue which now allows the bulk-id strategies to work even when you cannot create temporary tables.

Class diagram

Considering we have the following entities:

Class diagram, align=

The Person entity is the base class of this entity inheritance model, and is mapped as follows:

@Entity(name = "Person")
@Inheritance(
    strategy = InheritanceType.JOINED
)
public class Person
    implements Serializable {

    @Id
    private Integer id;

    @Id
    private String companyName;

    private String name;

    private boolean employed;

    //Getters and setters omitted for brevity

    @Override
    public boolean equals(Object o) {
        if ( this == o ) {
            return true;
        }
        if ( !( o instanceof Person ) ) {
            return false;
        }
        Person person = (Person) o;
        return Objects.equals(
            getId(),
            person.getId()
        ) &&
        Objects.equals(
            getCompanyName(),
            person.getCompanyName()
        );
    }

    @Override
    public int hashCode() {
        return Objects.hash(
            getId(), getCompanyName()
        );
    }
}

Both the Doctor and Engineer entity classes extend the Person base class:

@Entity(name = "Doctor")
public class Doctor
    extends Person {
}

@Entity(name = "Engineer")
public class Engineer
    extends Person {

    private boolean fellow;

    //Getters and setters omitted for brevity
}

Inheritance tree bulk processing

Now, when you try to execute a bulk entity query:

int updateCount = session.createQuery(
    "delete from Person where employed = :employed" )
.setParameter( "employed", false )
.executeUpdate();

Hibernate executes the following statements:

create temporary table
    HT_Person
(
    id int4 not null,
    companyName varchar(255) not null
)

insert
into
    HT_Person
    select
        p.id as id,
        p.companyName as companyName
    from
        Person p
    where
        p.employed = ?

delete
from
    Engineer
where
    (
        id, companyName
    ) IN (
        select
            id,
            companyName
        from
            HT_Person
    )

delete
from
    Doctor
where
    (
        id, companyName
    ) IN (
        select
            id,
            companyName
        from
            HT_Person
    )

delete
from
    Person
where
    (
        id, companyName
    ) IN (
        select
            id,
            companyName
        from
            HT_Person
    )

HT_Person is a temporary table that Hibernate creates to hold all the entity identifiers that are to be updated or deleted by the bulk id operation. The temporary table can be either global or local, depending on the underlying database capabilities.

What if you cannot create a temporary table?

As the HHH-11262 issue describes, there are use cases when the application developer cannot use temporary tables because the database user lacks this privilege.

In this case, we defined several options which you can choose depending on your database capabilities:

  • InlineIdsInClauseBulkIdStrategy

  • InlineIdsSubSelectValueListBulkIdStrategy

  • InlineIdsOrClauseBulkIdStrategy

  • CteValuesListBulkIdStrategy

InlineIdsInClauseBulkIdStrategy

To use this strategy, you need to configure the following configuration property:

<property name="hibernate.hql.bulk_id_strategy"
          value="org.hibernate.hql.spi.id.inline.InlineIdsInClauseBulkIdStrategy"
/>

Now, when running the previous test case, Hibernate generates the following SQL statements:

select
    p.id as id,
    p.companyName as companyName
from
    Person p
where
    p.employed = ?

delete
from
    Engineer
where
        ( id, companyName )
    in (
        ( 1,'Red Hat USA' ),
        ( 3,'Red Hat USA' ),
        ( 1,'Red Hat Europe' ),
        ( 3,'Red Hat Europe' )
    )

delete
from
    Doctor
where
        ( id, companyName )
    in (
        ( 1,'Red Hat USA' ),
        ( 3,'Red Hat USA' ),
        ( 1,'Red Hat Europe' ),
        ( 3,'Red Hat Europe' )
    )

delete
from
    Person
where
        ( id, companyName )
    in (
        ( 1,'Red Hat USA' ),
        ( 3,'Red Hat USA' ),
        ( 1,'Red Hat Europe' ),
        ( 3,'Red Hat Europe' )
    )

So, the entity identifiers are selected first and used for each particular update or delete statement.

The IN clause row value expression has long been supported by Oracle, PostgreSQL, and nowadays by MySQL 5.7. However, SQL Server 2014 does not support this syntax, so you’ll have to use a different strategy.

InlineIdsSubSelectValueListBulkIdStrategy

To use this strategy, you need to configure the following configuration property:

<property name="hibernate.hql.bulk_id_strategy"
          value="org.hibernate.hql.spi.id.inline.InlineIdsSubSelectValueListBulkIdStrategy"
/>

Now, when running the previous test case, Hibernate generates the following SQL statements:

select
    p.id as id,
    p.companyName as companyName
from
    Person p
where
    p.employed = ?

delete
from
    Engineer
where
    ( id, companyName ) in (
        select
            id,
            companyName
        from (
        values
            ( 1,'Red Hat USA' ),
            ( 3,'Red Hat USA' ),
            ( 1,'Red Hat Europe' ),
            ( 3,'Red Hat Europe' )
        ) as HT
            (id, companyName)
    )

delete
from
    Doctor
where
    ( id, companyName ) in (
         select
            id,
            companyName
        from (
        values
            ( 1,'Red Hat USA' ),
            ( 3,'Red Hat USA' ),
            ( 1,'Red Hat Europe' ),
            ( 3,'Red Hat Europe' )
        ) as HT
            (id, companyName)
    )

delete
from
    Person
where
    ( id, companyName ) in (
        select
            id,
            companyName
        from (
        values
            ( 1,'Red Hat USA' ),
            ( 3,'Red Hat USA' ),
            ( 1,'Red Hat Europe' ),
            ( 3,'Red Hat Europe' )
        ) as HT
            (id, companyName)
    )

The underlying database must support the VALUES list clause, like PostgreSQL or SQL Server 2008. However, this strategy requires the IN-clause row value expression for composite identifiers so you can use this strategy only with PostgreSQL.

InlineIdsOrClauseBulkIdStrategy

To use this strategy, you need to configure the following configuration property:

<property name="hibernate.hql.bulk_id_strategy"
          value="org.hibernate.hql.spi.id.inline.InlineIdsOrClauseBulkIdStrategy"
/>

Now, when running the previous test case, Hibernate generates the following SQL statements:

select
    p.id as id,
    p.companyName as companyName
from
    Person p
where
    p.employed = ?

delete
from
    Engineer
where
    ( id = 1 and companyName = 'Red Hat USA' )
or  ( id = 3 and companyName = 'Red Hat USA' )
or  ( id = 1 and companyName = 'Red Hat Europe' )
or  ( id = 3 and companyName = 'Red Hat Europe' )

delete
from
    Doctor
where
    ( id = 1 and companyName = 'Red Hat USA' )
or  ( id = 3 and companyName = 'Red Hat USA' )
or  ( id = 1 and companyName = 'Red Hat Europe' )
or  ( id = 3 and companyName = 'Red Hat Europe' )

delete
from
    Person
where
    ( id = 1 and companyName = 'Red Hat USA' )
or  ( id = 3 and companyName = 'Red Hat USA' )
or  ( id = 1 and companyName = 'Red Hat Europe' )
or  ( id = 3 and companyName = 'Red Hat Europe' )

This strategy has the advantage of being supported by all the major relational database systems (e.g. Oracle, SQL Server, MySQL, and PostgreSQL).

CteValuesListBulkIdStrategy

To use this strategy, you need to configure the following configuration property:

<property name="hibernate.hql.bulk_id_strategy"
          value="org.hibernate.hql.spi.id.inline.CteValuesListBulkIdStrategy"
/>

Now, when running the previous test case, Hibernate generates the following SQL statements:

select
    p.id as id,
    p.companyName as companyName
from
    Person p
where
    p.employed = ?

with HT_Person (id,companyName ) as (
    select id, companyName
    from (
    values
        (?, ?),
        (?, ?),
        (?, ?),
        (?, ?)
    ) as HT (id, companyName) )
delete
from
    Engineer
where
    ( id, companyName ) in (
        select
            id, companyName
        from
            HT_Person
    )

with HT_Person (id,companyName ) as (
    select id, companyName
    from (
    values
        (?, ?),
        (?, ?),
        (?, ?),
        (?, ?)
    ) as HT (id, companyName) )
delete
from
    Doctor
where
    ( id, companyName ) in (
        select
            id, companyName
        from
            HT_Person
    )


with HT_Person (id,companyName ) as (
    select id, companyName
    from (
    values
        (?, ?),
        (?, ?),
        (?, ?),
        (?, ?)
    ) as HT (id, companyName) )
delete
from
    Person
where
    ( id, companyName ) in (
        select
            id, companyName
        from
            HT_Person
    )

The underlying database must support the CTE (Common Table Expressions) that can be referenced from non-query statements as well, like PostgreSQL since 9.1 or SQL Server since 2005. The underlying database must also support the VALUES list clause, like PostgreSQL or SQL Server 2008.

However, this strategy requires the IN-clause row value expression for composite identifiers, so you can only use this strategy only with PostgreSQL.

Conclusion

If you can use temporary tables, that’s probably the best choice. However, if you are not allowed to create temporary tables, you must pick one of these four strategies that works with your underlying database. Before making your mind, you should benchmark which one works best for your current workload. For instance, CTE are optimization fences in PostgreSQL, so make sure you measure before taking a decision.

If you’re using Oracle or MySQL 5.7, you can choose either InlineIdsOrClauseBulkIdStrategy or InlineIdsInClauseBulkIdStrategy. For older version of MySQL, then you can only use InlineIdsOrClauseBulkIdStrategy.

If you’re using SQL Server, InlineIdsOrClauseBulkIdStrategy is the only option for you.

If you’re using PostgreSQL, then you have the luxury of choosing any of these four strategies.

Hibernate Community Newsletter 2/2017

Posted by    |       |    Tagged as Discussions Hibernate ORM

Welcome to the Hibernate community newsletter in which we share blog posts, forum, and StackOverflow questions that are especially relevant to our users.

Interviews

Don’t miss our Hibernate developer interview with Dmitry Alexandrov.

If you want to share your story about Hibernate, let us know, and we can share it with our huge community of passionate developers.

Articles

I was told about a new blog post which proclaims that Lazy loading is a code smell. Well, in my experience, this is exactly the opposite since I’m a strong believer that EAGER fetching is almost always a bad way of fetching data. After reading Sebastian Malaca’s article, I managed to find a very interesting series of article on mixing JPA and DDD (Domain-driven design).

DDD is a great approach. However, trying to treat a relational database as if it were a document store can be very detrimental to application performance. All in all, JPA entities are not the same as DDD entities. In fact, JPA entities are just the persistent state of the Domain Model.

Orlando L Otero wrote a tutorial about implementing a Multitenant architecture on top of Spring, Hibernate, and PostgreSQL. Related to Multitenancy, I found this Microsoft article from 2006 very relevant to the day.

Choosing the right entity identifier strategy requires some knowledge of the underlying JPA provider. For this reason, if you want portability, check out how you can replace the suboptimal TABLE strategy with SEQUENCE or IDENTITY.

Thorben Janssen wrote a short guide which introduces several JPQL query features. For more on this topic, check out the exhaustive JPQL and HQL chapter in the Hibernate 5 User Guide.

Hibernate entity queries are suitable when you want to modify the fetched entities, and taking advantage of the dirty checking mechanism. However, if you want to take advantage of advanced SQL query capabilities, you need native SQL queries. Check out this article to learn why native SQL queries are a Magic Wand.

Time to upgrade

Meet Dmitry Alexandrov

Posted by    |       |    Tagged as Discussions Hibernate ORM Interview

In this post, I’d like you to meet Dmitry Alexandrov, who, not only that he’s a well known Java technologist and conference speaker, but he’s also a polyglot, speaking 6 languages (e.g. Russian, Bulgarian, Ukrainian, English, German, and French).

Dmitry Alexandrov, align=
  1. Hi, Dmitry. Would you like to introduce yourself and tell us a little bit about your developer experience?

    Hi! My name is Dmitry Aleksandrov and currently for more than a year I’m a Principal expert developer and architect at T-Systems. I’ve got 10 years experience mainly in Java EE/Spring stack.

    Most of my time I was dealing with big enterprise projects in banking, insurance, and telecoms. Along with four other awesome guys, I’m a co-lead in the Bulgarian Java User Group and jPrime conference co-organizer.

  2. You have recently published an article about a major performance optimization you underwent in one enterprise project. Can you tell us what are the most common performance issues in enterprise systems?

    Surprisingly, or actually not so much surprisingly, the most of the optimizations in enterprise projects are made on the persistence layer. The way the data is stored and accessed is essential as the most of the latency may come out of there.

    The other source of latency may be the remote calls, but the only way gain performance there is to reduce their quantity and upgrade the hardware architecture. As for the persistence much more can be done in this field. It is essential to really pay attention to what is taken out the DB and what is shown to the user. Heavy CPU processing is rarely seen, at least from my experience.

    So. it is really important to invest time in a good design of the persistence layer. ORMs are doing really great job, and the automation they have brought saves tremendous efforts, time and money. But at the same time, the users of the ORMs are a little bit spoiled of the magic they bring.

    The developers and architects tend to design the object model as the primary source of data and the DB schemas as a product of the model and heavily rely on the ORM to manage this. This quite often leads to very suboptimal data representation in the RDBMS thus performance issues, since the mathematics in Relational Databases are much different from those of the programming language objects. And those mistakes are often very hard and expensive to fix, as DB schemas are extremely hard to change especially when they are in production already.

    And the ORM, although it is an extremely smart tool nowadays, is still not an AI (yet). So to deal with those problems, I believe that every enterprise or full stack developer should invest more time in educating in Databases and the way their programming language interacts with them. A good persistence layer design may solve the most of the performance issues or even fully prevent them from happening.

  3. Hibernate offers many optimizations that aim to increase application performance. Has Hibernate met your goals in the projects you’ve been involved with?

    Yes, definitely. Although we try to use as much standard JPA as possible, on our final customer deployments we also do Hibernate specific optimizations, like pre-build code instrumentation if we use Hibernate version 5. In one of my previous project we have used some second-level caching, and Hibernate integrated almost seamlessly.

  4. You are a Java EE aficionado and international speaker. How to you see the future of Java EE and JPA in the context of cloud computing and Microservices architectures?

    Java EE is a subject of many discussions recently. Quite a lot of even fatal prognoses were made, but I personally believe Java EE will still be there and make big progress. There is a huge аmount of companies and enterprises that build their business with Java EE technologies, and they won’t disappear soon since EE is a proven standard.

    Actually, this is the main advantage of Java EE – it is a standard. It means it is guaranteed, a reliable and tested set of functionalities that have the same behavior and results on all supported platforms. And a standard is not something that is just assigned, standards are established based on what’s the best and most valuable in current technology at the moment. And the establishment of these technologies the most often comes from the community.

    A good example of community effort is exactly the Microprofile initiative, which is driven by Independent Java EE Server vendors. As Microservices are now very popular, the activists try to create a really common solution for the best utilization of this architecture on Java EE.

    Although there are some controversies about what should this profile include, there is a starting point. The discussion is open, and everybody is welcome to contribute. Actually, it is very curious to see how a standard is being born! The guys are doing a great job! Another example is the Java EE Guardians who are doing great input in all aspects of the Java EE evolution!

    As for the cloud, Oracle has made some promises that they will put more efforts in a better Java EE cloud integration. But as for now in our environments, we have a mixture of PaaS and IaaS solutions. Like some of the servers are Dockerized or packed as executable jars and running somewhere in the cloud, and the databases are provided like services. But there we have some issues with the latency.

  5. We always value feedback from our users, so can you tell us what you’d like us to improve or are there features that we should add support for?

    I am now waiting for the full support of the Entity Graph functionality. I personally believe that’s a very handy way to have a good fine control over what you fetch and can give some really good performance improvements, especially on systems which are in production already.

Thank you, Dmitry, for taking your time. It is a great honor to have you here. To reach Dmitry, you can follow him on Twitter.

Hibernate Community Newsletter 1/2017

Posted by    |       |    Tagged as Discussions Hibernate ORM

Welcome to the Hibernate community newsletter in which we share blog posts, forum, and StackOverflow questions that are especially relevant to our users.

Articles

Dmitry Alexandrov wrote an awesome article which explains how he managed to optimize the memory allocation of an enterprise application so that, instead of occupying 8 GB, it now requires only 89 MB of Heap storage.

If yu are using the TABLE identifier generator, you should know that this generator does not scale very well. Check out this article for more details.

For our Portuguese readers, Daniel Dias wrote an article about how you can persist data into a NoSQL database using Hibernate OGM.

Thorben Janssen continues his Hibernate Envers series with an article about extending the standard revision.

Time to upgrade

Hibernate Community Newsletter 25/2016

Posted by    |       |    Tagged as Discussions Hibernate ORM

Welcome to the Hibernate community newsletter in which we share blog posts, forum, and StackOverflow questions that are especially relevant to our users.

Articles

Sanne Grinovero and John Griffin have worked on the Getting Started with Hibernate Search RefCard on DZone. Check out the PDF version which is even more detailed than the web version.

If you want to customize the JOIN clause of an entity association, you can use the Hibernate @JoinFormula annotation, as explained in this article.

There are multiple ways to delete a JPA entity, as illustrated in this article on Baeldung.

Thorben Janssen wrote a Getting Started article for Hibernate Envers and another one about querying audit log entries.

Dimo Velev gives a very detailed explanation of why Class.forName can cause lock contention. The HHH-4959 was affecting both JPQL and Criteria API entity queries, and the fix will be available starting from Hibernate ORM 5.2.6.

If you want to use Hibernate ORM with SQL Server, then you should read this article. There are plenty of tips related to optimal data access patterns and indexing considerations.

Jakub Kubrynski explains why you should care about equals and hashCode, especially when dealing with JPA entities.

Hibernate Community Newsletter 24/2016

Posted by    |       |    Tagged as Discussions Hibernate ORM

Welcome to the Hibernate community newsletter in which we share blog posts, forum, and StackOverflow questions that are especially relevant to our users.

Interviews

Don’t miss our Hibernate developer interviews with Christian Beikov and Simon Martinelli.

If you like our interviews, then we have good news since we are going to interview many developers that are a constant inspiration for our Java community.

Articles

If you plan on using Apache Ignite, check out this article about using Hibernate OGM when operating with a JPA-based Domain Model.

Database streaming is usually associated with large data set processing. However, there is a price to pay for using streaming. This article explains why pagination might be a better option in many batch processing use cases.

Blaze Persistence offers many complementary features to standard JPA Criteria API. In this post, Christian Beykov explains why you should use Entity Views when fetching data.

Flemming Harms wrote a very good article about integrating JPA with Apache Camel.

Thorben Janssen shows you how you can generate the database schema from JPA entities. While this is fine for generating an initial migration script, in reality, you need incremental migration scripts that are managed by a tool like Flyway. Check out this article for more info.

Multitenancy is a very powerful concept, and JavaEE 8 might standardize this technique. Meanwhile, you can use Hibernate ORM as explained in this article.

IntelijIDEA 2016.3 offers a very nice console for running JPQL queries and visualizing query results. Check out this article for more info.

In this post, I’d like you to meet Simon Martinelli, who, among many other things, is teaching Java EE and JPA at the University of Applied Sciences in Berne.

Simon Martinelli, align=
  1. Hi, Simon. Would you like to introduce yourself and tell us a little bit about your developer experience?

    I’m a software architect, developer, and trainer from Switzerland working for simas GmbH. Besides that, I’m a lecturer for Java EE, architecture and design and persistence technologies at the University of Applied Sciences in Berne. In my spare time, I’m working on some open source projects and as I’m an expert group member of JSR 352 Batch and JSR 354 Money and Currency API.

    I started my IT career in 1995 as a Cobol developer on IBM mainframe. Since 2000, I’ve been working in many enterprise projects as a developer, architect, and technical lead, using J2EE/Java EE, Spring framework, and from time to time .NET. My first contact with OR-Mapping was in 2000 when we used TopLink in a project for Swiss Railways.

  2. You have an open-source project on GitHub called Query Language Result Mapper. Can you tell us what’s the goal of this framework?

    I love the JPA constructor expression. In my opinion, it’s the best way to get around the common performance problems when using JPA in a naive way. But the constructor expression only works with JPQL or Criteria API and sometimes you need to execute a SQL query but don’t want to use a fully featured SQL framework like jOOQ.

    Sure, JPA comes with the ConstructorResult but I find it too complicated, and it was not available with JPA 1.0. Hibernate has the ResultTransformer, but this only works with Hibernate. So I decided to start Query Language Result Mapper (QLRM).

    QLRM simply tries to find a matching constructor based on a JPA native query result or, when using plain JDBC, a JDBC ResultSet. It’s simple, small and not related to a specific JPA implementation.

  3. You are also teaching Java EE and Java Persistence API at the University of Applied Science in Berne. Is JPA easy to learn? What do your students think of this Java Persistence standard?

    JPA is by far the most complicated part of Java EE to learn. Because it’s leaky abstraction, you have to know a lot about SQL databases and what’s going on behind the scenes. It’s also the most common source of performance problems. While teaching, I always try to focus on how to avoid these performance problems.

    My students usually like JPA because it makes data access much easier. For those who don’t know the history of OR-Mapping, it’s hard to understand that the JPA implementation behaves differently in some situations. What they don’t like is that (currently) JPA does not support the Java 8 Date Time API.

  4. Since I started blogging, I realized that explaining a subject helps me better understand it. Do you think all developers should be involved in teaching or writing articles or books about the subjects they want to master?

    Absolutely! I’m teaching JPA since 2007, and this forces me to get a deep understanding of the topic because the questions of the students can be very challenging. Sometimes I even have to look at the code of the JPA implementation to understand what happens under the hood. In return, this know-how helps me to write better and faster applications.

    As Albert Einstein said: "If you can’t explain it simply, you don’t understand it well enough."

  5. We always value feedback from our users, so can you tell us what you’d like us to improve or are there features that we should add support for?

    I think the whole Hibernate team is doing a great job! It’s more than feature-complete (it’s hard to know every feature, though).

    Just one minor thing: When reading the documentation it’s often hard to differentiate what’s JPA standard and what’s Hibernate specific. But I don’t think that this is very important because not many developers are switching the JPA implementation in a project.

Thank you, Simon, for taking your time. It is a great honor to have you here. To reach Simon, you can follow him on Twitter.

In this post, I’d like you to meet Christian Beikov, who is one of the most active Hibernate contributors.

Christian Beikov, align=
  1. Hi, Christian. Would you like to introduce yourself and tell us a little bit about your developer experience?

    Hey, Vlad. My name is Christian Beikov, and I am 25. I’m living with my girlfriend in Vienna, the capital city of Austria. I started working with Java EE technologies in school and continued to do so at my first job where I am still employed part-time. Next to my job, I am doing my master studies in Software Engineering at TU Wien which I am hopefully finishing next year.

    My main interests are in distributed systems, database technologies and everything Java/JVM-related. In school, I came into contact with Java EE for the first time when I was by developing a JSF-based web app with Hibernate on top of GlassFish with NetBeans. When I started my job at Curecomp GmbH, I mainly worked with Eclipse and WebSphere and about 2 years ago, I managed to fully migrate the company’s development stack to WildFly and IntelliJ IDEA. During these migrations and the countless university assignment projects in which I have used Hibernate, I’ve stumbled upon one or another bug.

  2. You’ve been very active in the Hibernate ecosystem, sending Pull Requests and getting involved in future design discussions. How do you manage to blend the open-source involvement with your day job?

    The work I am doing in open-source projects happens mostly in my free time. I like to give back something to the community, even if it’s just bug reports. Since I use Hibernate in so many projects, I also see my contributions as an investment in improving the overall quality of the projects I do.

    At my day job, I am sometimes facing problems that I simply can’t workaround or doing a proper fix seems equally hard to me, which is how I justify fixing the Hibernate bug in the core. The deep knowledge that I gain from analyzing bugs and discussing features also helps me in my day job when reasoning about the behavior of Hibernate in certain situations which is a big plus.

  3. You are also developing Blaze Persistence. Can you tell us a little bit about this framework and how does it compare to Criteria API?

    Blaze-Persistence is a library on top of the JPA APIs. The core module provides a fluent query builder API that allows you to express queries in a Java DSL which should feel mostly intuitive. In addition to the standard features that are defined in JPA 2.1, it also implements support for some common functionality that already every JPA provider supports like for example aliasing fetch joins or entity joins. On top of that, Blaze-Persistence also provides deep integration with the JPA provider to support features like (recursive) CTEs or set operations like UNION, etc. Beware that the deep integration is currently only available for Hibernate since it is the provider I am mostly familiar with, but support for others is planned.

    One of the greatest features that Blaze-Persistence makes possible are Entity Views which are to JPA entities roughly what views are to tables in the RDBMS sense. An Entity View is an interface or abstract class that represents the structure of a projection for an entity. It’s basically the definition of a DTO, with the difference that you only need to specify getter methods along with the projection for that attribute as JPQL expression. When you then apply the Entity View on a base query, it will contribute the JPQL expressions as select items, thus creating an optimized JPQL and SQL query. The result of such a query, of course, is a list of objects that are a subtype of the Entity View. Apart from avoiding all the manual plumbing code to get the data into shape, you can make use of features like Collection mappings, Subviews or SubqueryProviders which let you define complex projections that one would normally not do.

    The Criteria API provided by JPA is hard to use as it requires a lot of typing and also some kind of skill. You need to know how to wire things up which is one of the big pain points that I tried to solve by introducing a fluent API. Sure the JPA Criteria API is type-safe, but that comes at the cost of obfuscating your query. A type-safe variant of the Blaze-Persistence core API or maybe even just some additional methods in the existing API are already on my roadmap, so I will also try to fill this gap while retaining readability.

    Since I don’t expect everyone to rewrite his existing JPA Criteria API based queries, I also implemented the JPA Criteria API on top of the Blaze-Persistence core API. You can even let your existing code build the queries with the JPA Criteria API and retrieve a Blaze-Persistence query builder from it. The resulting query builder can be used just like any other query builder which means you can use CTEs and all the other great features.

  4. Blaze Persistence works with any JPA provider. From your experience, how does Hibernate ORM compare to EclipseLink or OpenJPA?

    Just as a disclaimer, I haven’t dug too much into the communities of the other JPA providers as I don’t use them in any of my projects. Also, beware that I might be biased now since I know people from the Hibernate team and know who to contact if I have a problem, but I’ll try to be as neutral as possible.

    I got the feeling that the EclipseLink community didn’t care about the bugs I reported or forum posts I did, but apart from that, the implementation seems ok. It has some quirks like e.g. allowing lazy loading although the underlying entity manager is closed, but maybe that’s a feature :D

    DataNucleus which is one of the lesser known JPA providers is actually pretty good and the main developer there reacts super fast to bug reports. I found some bugs and also proposed some features to increase Hibernate compatibility and as far as I know, all of these issues have been resolved by now.

    I can’t tell you much about OpenJPA except that it seems rather dead or in maintenance mode only to me. The latest version is only JPA 2.0 compatible and unfortunately, lacks even proprietary ways to do certain things that are possible with other JPA providers.

    The thing I am mostly unsatisfied with is that most of the issues I found with any JPA provider are pretty basic things and should be asserted by the JPA TCK. I hope some Oracle guy who can actually do something reads this and pushes harder to make the JPA TCK open-source :)

  5. We always value feedback from our users, so can you tell us what you’d like us to improve or are there features that we should add support for?

    I think Hibernate already does a very good job. What I really would like to see is the decoupling of the SQL generation and execution from the ORM specifics. This is something I often would have needed in one way or another to workaround bugs or simply to execute the SQL that is needed for a specific task. Imagine you could specify a HQL query that just describes how the result mapping should be done, but specify your own SQL. This is something I am doing internally in Blaze-Persistence all the time for advanced queries. I hope the SQM feature that is planned for Hibernate 6 will allow me to do that so I can get rid of the dirty tricks I have to do right now to get stuff done.

Thank you, Christian, for taking your time. It is a great honor to have you here. To reach Christian, you can follow him on Twitter.

Hibernate Community Newsletter 23/2016

Posted by    |       |    Tagged as Discussions Hibernate ORM

Welcome to the Hibernate community newsletter in which we share blog posts, forum, and StackOverflow questions that are especially relevant to our users.

Articles

Don’t miss our Hibernate developer interviews with Rafael Winterhalter and Julien Dubois. If you like our interviews, then we have good news since we are going to interview many developers that are a constant inspiration for our Java community.

When streaming data from a Relational Database, it’s very important to understand the underlying JDBC Driver capabilities. Krešimir Nesek wrote a very good article about how you can take advantage of MySQL streaming when using Spring Data and Hibernate.

You should never concatenate strings when building dynamic queries, and this rule applies to JPQL queries as well. Check out this article for what dangers awaits you if you don’t follow this advice.

Nicky Bass Mølholm wrote a wonderful article explaining the benefit of using the newly introduced hibernate.jdbc.time_zone configuration property when using Spring Boot.

Matti Tahvonen has created Spring Boot example with Hibernate Spatial. You can check it out on GitHub.

In this post, I’d like you to meet Rafael Winterhalter, Java Champion, JavaZone conference organizer, and Team Leader of Byte Buddy.

Rafael has done a great job migrating Hibernate from Javassist to Byte Buddy, for which we are very grateful.

Rafael Winterhalter, align=
  1. Hi, Rafael. Would you like to introduce yourself and tell us a little bit about your developer experience?

    Hei, I am Rafael, a native German who is living in Oslo, Norway where I work as a software consultant.

    Before that, I was in academia where I did a fair share of statistical analysis what evoked an interest in computer performance. After I left university, I have been working mostly with the JVM where I still enjoy working with performance critical systems but where I also do a lot of enterprise software development.

    I am also quite active in open source and as a conference speaker and organizer.

  2. You are the Team Leader of the Byte Buddy open-source framework. Can you tell what’s the goal of Byte Buddy?

    Byte Buddy originated out of frustration over cglib, a commonly used library for code generation that got abandoned a few years back. I was working on a proxy component that needed to retain the annotations of the proxied methods.

    Proxies are often implemented as subclasses where these annotations disappear as method annotations are never inherited. Many libraries such as Hibernate do however use annotations as part of their API what breaks this pattern. I got stuck and wrote a tiny library as a replacement for cglib which later evolved into what is Byte Buddy today.

    Today, the library‘s goal is to be the fastest and easiest way to define or modify Java classes at runtime. As a side goal, I wanted to offer some support for Android which was previously lacking a runtime code generation library and I wanted to make it easy to define Java agents.

  3. In 2013, you wrote the cglib: The missing manual article. How does Byte Buddy compare to cglib or javassist?

    I wrote this article as a heavy user of code generation libraries in open source and to share a bit of my knowledge of cglib which is not supplemented by any documentation. I still believe that this is one major issue of code generation libraries; due to the lack of documentation, many people fear using them for not understanding how they work despite their usefulness.

    Other than Byte Buddy, cglib is limited to creating subclasses of existing types where it can override existing methods. Byte Buddy gives you full freedom in defining additional fields or methods and allows you to implement methods arbitrarily. In practice, this often results in thinner byte code and better performance.

    Also, Byte Buddy does not require you to include any library-specific classes into the generated code what is crucial for OSGi-environments. Also, this will become a necessity when working with Java 9 modules which the authors of cglib did of course not anticipate 15 years back.

    Javassist has a proxy API that is similar to cglib which does, however, come with the identical limitations. Additionally, Javassist allows for arbitrary modifications of classes using a different API by supplying Java code as strings. While this approach gives you full freedom, it is very vulnerable to API-changes which then yield runtime errors and also opens up to code-injection when processing user input, similar to SQL-injection when using JDBC.

    Byte Buddy rather works with precompiled code which can be written in any JVM language and which can be inlined at runtime. Avoiding runtime compilation makes Byte Buddy’s transformations type-safe and much faster to apply at runtime.

  4. You have contributed to many open-source projects, Byte Buddy, Mockito, and now Hibernate ORM. Can you tell us more about the Hibernate and Byte Buddy integration?

    The usage of Byte Buddy in Hibernate ORM and Mockito differs a lot.

    Hibernate mostly uses code generation to implement runtime proxies. For the Hibernate enhancer, it does, however, require some rather fundamental changes of a code base by installing its own callbacks into classes in order to better monitor an object’s state. Fortunately, all such enhancement is done in a dedicated step what makes the code manipulation quite predictable.

    In Mockito, we traditionally only required simple subclass proxies. In Mockito 2, we added, however, a new mock maker that inlines the mocking logic at runtime. This way, it becomes possible to mock final classes and methods what is important in order to support new JVM languages such as Kotlin where, by default, all methods are final. With this new mock maker, Byte Buddy needs to rewrite large fractions of a class.

  5. We always value feedback from our users, so can you tell us what you’d like us to improve or are there features that we should add support for?

    Hibernate has been my first choice for an O/R Mapper in many years, and I am very happy how well it works. One critique I had was the lack of documentation.

    People are often abusing the library’s capabilities or run into performance issues because they do not understand what the library is doing and what its intended use case is. And to be fair, this is not always easy to figure out.

    I feel like the state of documentation has improved a lot in the last time, and I very much welcome this effort.

Thank you, Rafael, for taking your time. It is a great honor to have you here. To reach Rafael, you can follow him on Twitter.

back to top