cheb1k4 February 2016

How to use PreparedStatement efficiently?

I like to use the DAO pattern and have a class which do all my SQL request for a particular table and JPA entity. I have for example something like:

public class MyDao {

    @PersistenceContext(name = "mycontext")
    private EntityManager entityManager;

    public List<MyEntity> find(String code)  {

        return getEntityManager()
            .createQuery("FROM MyEntity e WHERE e.code = :code")
            .setParameter("code", code)
            .getResultList();

    }

}

But I also know we can use named query directly on the entity class with a static method (I don't like this way):

@Entity
@Table
@NamedQueries({
    @NamedQuery(name = "find", query = "FROM MyEntity e WHERE e.code = :code")
})
public class MyEntity {

    ...

    public static List<MyEntity> find(EntityManager entityManager, String code) {

        return entityManager.createNamedQuery("find", MyEntity.class)
            .setParameter("code", code)
            .getResultList();

    }

}

Is one of those method better than the other one ? If I want to execute the same SQL query thousands of times in the same transaction, is both methods keep in JPA memory (or somewhere else) the prepared statement ? Which seems to be a good practise in this case. I would think the second method does it because it's static but not the first one. Am I wrong ?

Answers


sagneta February 2016

The advantage for declaritively defined queries via @NamedQuery is that they will be precompiled, can be cached within the secondary cache and syntactically validated on startup if you enable it within the persistence.xml using the JPA non-hibernate specific API.

So if you plan on executing a query, using only JPA, often it is probably best to use NamedQuery and cache the query.

So for JPA using hibernate you could do something like this:

            @NamedQuery(name="AbstractBaseQuestion.findAllInstancesByGroupID", query="SELECT q FROM AbstractBaseQuestion q WHERE q.isTemplate = FALSE", hints={@QueryHint(name="org.hibernate.cacheable", value="true"),@QueryHint(name="org.hibernate.cacheMode", value="NORMAL"),}),

Within your persistence.xml for hibernate you can validate these @NamedQueries on startup:

      <property name="hibernate.hbm2ddl.auto" value="validate"/>

Now the first method you suggested can be cached and precompiled if you use the Hibernate Session API. I imagine there are equivalents on EclipseLink and other ORM's but at this point you are using non-JPA features which could make moving from one JPA implementation to another difficult.

If you don't do that extra implementation specific work your query is going to not be cached and you will pay a performance penalty.

I hope that helps.

Post Status

Asked in February 2016
Viewed 3,420 times
Voted 9
Answered 1 times

Search




Leave an answer