views:

49

answers:

4
+1  A: 

What you want is a NamedQuery. On your Order entity you put:

@NamedQueries({
    @NamedQuery( name = "getOrderByCustomerId" query = "SELECT o FROM Order o WHERE o.customerId = :customerId")
})

Then in your DAO use em.createNamedQuery("getOrderByCustomerId") instead of recreating the query.

Affe
+1  A: 

NamedQueries is the concept you're looking for.

Chris Lercher
+3  A: 

Use statically defined named queries. They are more efficient because the JPA persistence provider can translate the JP QL string to SQL once at application startup time, as opposed to every time the query is executed, and are recommended in particular for queries that are executed frequently.

A named query is defined using the @NamedQuery annotation that is typically used on the entity class of the result. In your case, on the Order entity:

@Entity
@NamedQueries({
    @NamedQuery(name="Order.findAll",
                query="SELECT o FROM Order o"),
    @NamedQuery(name="Order.findByPrimaryKey",
                query="SELECT o FROM Order o WHERE o.id = :id"),
    @NamedQuery(name="Order.findByCustomerId",
                query="SELECT o FROM Order o WHERE o.customerId = :customerId")
})
public class Order implements Serializable {
    ...
}

It is also recommended to prefix named queries with the entity name (to have some kind of name space and avoid collisions).

And then in the DAO:

class OrderDao {
    EntityManager em;

    List getOrders(Long customerId) {
        return em.createNamedQuery("Order.findByCustomerId")
                 .setParameter("customerId", customerId);
                 .getResultList();
    }
}

PS: I reused the query you suggested as example but it's somehow weird to have the customerId on the Order, I would expect a Customer instead.

References

  • JPA 1.0 Specification
    • Section 3.6.4 "Named Queries"
Pascal Thivent
Thanks, NamedQueries concept is what I should to learn. Unfortunately a lot of my queries are built in runtime. Is there a way to "prepare" a run-time built query in JPA?
Andrey
Named queries also have the advantage of being validated during server startup which will throw errors when the query does not work due to changes to your model. This protects you from being surprised by a rare query not working anytime later when its actually used.
Daniel Bleisteiner
@Andrey: The behavior with other queries than *named queries* is implementation specific (what is true with Hibernate might not apply with another JPA provider).
Pascal Thivent
@Daniel Yes, absolutely, that's another benefit.
Pascal Thivent
+1  A: 

The is a query plan cache in Hibernate. So the HQL is not parsed every time the DAO is called (so #1 really occurs only once in your application life-time). It's QueryPlanCache. It's not heavily documented, as it "just works". But you can find more info here.

Thierry-Dimitri Roy
Thank you, that's cool. So can I simply be happy with this fact or I have to turn on this QueryPlanCache in Hibernate configuration?
Andrey
No, it's part of your framework since Hibernate is a "modern powerful ORM"! :)
Thierry-Dimitri Roy