Criteria API - Hibernate vs JPA 2

11

I'll try to phrase this question as unthinkingly as possible in the spirit of stackoverflow in English. For a new project I need to make the decision between using the JPA 2 or Hibernate API (while it is technically possible to mix the two, for architectural reasons we will have to choose between one or the other).

I have a team of Hibernate developers who know a lot about HQL and Criteria's native API.

Particularly, as someone who has read the book Pro JPA 2 from end to end, I think JPQL is sufficiently similar to HQL so that the transition is not problematic.

On the side of the Criteria API, which is widely used by developers, the difference is much more significant. While the JPA 2 API seems to me to be much more powerful than Hibernate it has a learning curve for developers: metamodel, strongly typed queries, etc.

The positive side is that in addition to making the project independent of the ORM provider, the new API has several useful features to support the having clause (open problem in hibernate since 2005 that has always brought us headaches).

My question then is. Is anyone of you using the JPA 2 Criteria API on large projects? Anyone who has experience with both APIs could do a comparative of pros and cons of each one?

    
asked by anonymous 18.12.2013 / 15:17

2 answers

10

Choosing which API to use would not only be a handy choice in code, but one should also think about architecture. I'll describe what I think about the two:

Architecture Considerations

The advantage of using the JPA's native Criteria API is that:

  • You will have more flexibility to change implementation, you can keep the JPA code used. As only the JPA interfaces will be used, such as Eclipse, OpenJPA, Hibernate, etc. will have these interfaces implemented.
  • Any new features you add in a new version, you'll already have access
  • You have the option to use criteria in a typed or not, typed mode already shows compile-time error
  • Allows complex queries to be performed, and if there is an implementation error (hibernate for example), just do a provider portability (go to EclipseLink for example)
  • The disadvantage of using the native JPA API is:

  • Complexity. Due to the large number of classes that exist in the native API, knowing all of them and their goals will take a long time
  • Verbosity. It is a very verbose API, a simple command like select leads to several lines of code
  • The advantage of using the Hibernate Criteria API is that:

  • Simple and easy to use code
  • Access features that will not be present in the native API
  • The disadvantage of using the Hibernate Criteria API is that:

  • You will be stuck with an implementation. If Hibernate is a problem, you will have trouble migrating to another implementation. Some time ago, for example, Batoo was released that promised a performance 15x faster than Hibernate. Imagine your project is experiencing performance issues and would you like to test this new implementation? When using Hiberate API this test would take a long time. Already with JPA native API would be done faster.
  • Artifact Size. Unfortunately, Hibernate has many dependencies, so the size of the war / ear increases considerably. This could be a problem when uploading the artifact to the production environment does not have a good internet link.
  • Code Considerations

    Here's how a select * from person (entity Person) will look when using the JPA criteria:

    CriteriaQuery<Person> criteriaQuery = criteriaBuilder.createQuery(Person.class);
    Root<Person> root = criteriaQuery.from(Person.class);
    criteriaQuery.select(root); // necessário caso uma condição where seja adicionada na consulta
    TypedQuery<Person> query = entityManager.createQuery(criteriaQuery);
    query.getResultList();
    

    Several lines of code to perform a simple query. As said, complexity and verbosity are unfortunately great. Here's how the same query looks using Hibernate:

    Criteria criteria = session.createCriteria(Person.class);
    List persons = criteria.list();
    

    Note that the code was much smaller and simpler to run, except that there was the addition of the Hibernate code itself.

    What to choose?

    Some questions could be asked to decide which criteria to use:

  • What is the level of the team that will maintain the project?
  • Is it possible for a small training in criteria to be given to the entire team?
  • Can my project have very complex queries using criteria?
  • Can the project have performance issues?
  • Are there solutions for using native API?

    There are frameworks on the market that work with the native JPA API and make it easier to use criteria. One of them is EasyCriteria ( link ). The same queries performed above could be done as below:

    EasyCriteria<Person> easyCriteria = EasyCriteriaFactory.createQueryCriteria(entityManager, Person.class);
    easyCriteria.getResultList();
    

    The advantage of using this type of framework is that you could migrate from Hibernate to OpenJPA, for example.

    Another solution would be QueryDSL that also has an interface to make it easier to query and create typed criteria (I do not know if untyped criteria works). In this case you would generate a meta model and then use QueryDSL to generate the criteria.

        
    18.12.2013 / 19:55
    4

    I will try to respond objectively, but also analyze technology choices in general terms.

    About API Choices

    First, the idea of vendor independence that many APIs sell is tempting but, in most cases, it hardly ever occurs. Take the case of application servers, for example. Can anyone distribute the same WAR on Tomcat, JBoss, Glassfish or Weblogic? Each contains specific features that vary immensely from one to another. On the other hand, if you completely ignore the features of your application server, you will lose the advantages of using it.

    In practice, you should choose from the available options that seem to best suit your project requirements without wasting too much time on it, as it probably is not worth going into too much detail when it comes to mature and commonly used products on the market. Of course there will be wrong choices and this is a real risk, so here is very much the experience and experience of the team and the leader.

    Hibernate or JPA?

    Now specifically speaking of JPA and Hibernate, I can say that JPA really has made great strides, but sometimes you may need a unique Hibernate feature, such as Dynamic Queries or User Types ( Update ): Hibernate 4.3 implements the JPA 2.1 specification and has the% it is no longer necessary to use a User Type to map an Enum or non-standard type. Anyway, the important thing is the idea represented in the text.).

    Which one to choose then? The answer is: neither one nor the other . You can use both APIs at the same time. As a suggestion, JPA might have preference, but the hibernate API would be used when needed. Particularly I had no trouble doing this.

    Hibernate Example # 1 + JPA: Dynamic queries

    Using a dynamic query does not include null fields in commands such as @Converter , for example, so the default value of the database will be used. In Hibernate this can be done through XML mapping or the annotations INSERT and @org.hibernate.annotations.Entity (in the most recent versions).

    But, suppose you already have a persistence.xml and a JPA entity like below:

    @javax.persistence.Entity
    public class MinhaEntidade { ... }
    

    What now? Just add the Hibernate annotation:

    @org.hibernate.annotations.Entity
    @org.hibernate.annotations.Entity(dynamicInsert = true)
    public class MinhaEntidade { ... }
    

    Hibernate Example # 2 + JPA: Session Access

    What if I have some HQL feature that would greatly improve one of the features? No problem, just unpack the @DynamicInsert of Hibernate:

    Session session = entityManager.unwrap(Session.class);
    

    Impact of this approach

    Obviously, following these examples, the implementation would be "tied" to Hibernate.

    However, the impact of a change, which I believe there will always be, will be minimized to some specific functionality.

    Finally, what is the real chance of needing to trade Hibernate for another JPA implementation in the near future? I'm not trying to say that Hibernate is absolutely superior, but the chances of someone needing a feature that only exists, let's suppose, in EclipseLink, and there is no available workaround, are minimal.

        
    18.12.2013 / 16:14