Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA why use createNamedQuery

I'm in the processes of changing my DAO layer from using Hibernate API to using a pure JPA API implementation. It looks like the recommended method is to use the createNamedQuery from the entity manager. The named queries are stored in annotations in the model/entity classes. This just not makes sense to me. Why would you define the JPA Queries in the model objects but use them in the DAOs. Wouldn't it make more sense to just use createQuery from within the DAO itself and define the queries in the DAO or even just define the named queries in the DAO itself?

For those of you that have implemented your DAO layer using the JPA API how have you defined your queries?

like image 313
Ruggs Avatar asked May 07 '09 03:05

Ruggs


4 Answers

I use named queries.

There are two reasons to do so:

  1. It puts them in a more central place rather than scattered in code with random createQuery() calls; and
  2. Build processes can validate the queries (really useful).
like image 168
cletus Avatar answered Oct 07 '22 17:10

cletus


You could take a look at Spring Data JPA. It allows you to simply define an interface and execute queries without the need to implement the execution manually.

Entity:

@Entity
@NamedQuery(id="User.findByLastname" query="from User u where u.lastname = ?1")
public class User implements Persistable<Long> {

  @Id
  private Long id;
  private String username;
  private String lastname;
  private int age;
}

Repository:

public interface UserRepository extends CrudRepository<User, Long> {

  // Will trigger the NamedQuery due to a naming convention
  List<User> findByLastname(String lastname);

  // Will create a query from the methodname
  // from User u where u.username = ?
  User findByUsername(String username);

  // Uses query annotated to the finder method in case you
  // don't want to pollute entity with query info
  @Query("from User u where u.age > ?1")
  List<User> findByAgeGreaterThan(int age);
}

Setup:

EntityManager em = Persistence.getEntityManagerFactory().createEntityManager();
JpaRepositoryFactory factory = new JpaRepositoryFactory(em);

UserRepository repository = factory.getRepository(UserRepository.class);

As you see you can choose between different ways to derive the query to be executed from the method. While deriving it directly from the method name is feasible for simple queries you'd probably choose between the @NamedQuery (JPA standard) or @Query (Spring Data JPA annotation) dependening on how much you like to stick with standards.

Spring Data JPA gives you support in various other corners of data access layer implementation, allows providing custom implementations for methods and nicely integrates with Spring.

like image 25
Oliver Drotbohm Avatar answered Oct 07 '22 19:10

Oliver Drotbohm


I had experience completely opposite to the one of cletus - I found no benefit and also found them awkward to use. Trivial queries would make no difference where to define, but non-trivial queries are usually hard to associate with any single entity but easy with business-oriented method.

If you use more or less sophisticated infrastructure in DAOs (for re-use and consistency) then usage of named queries tend to complicate both implementation and readability with no apparent benefit to offer.

Validating of queries by build process sounds interesting - I would like to know more what it really means... My queries leave little margin for error since every DAO method is unit tested as much as it makes sense.

like image 28
topchef Avatar answered Oct 07 '22 18:10

topchef


Don't just use named queries everywhere, there are cases where they are not appropriate, such as when its gonna be rarely used queries then it may be more efficient when built on as needed basis.

Named queries make more sense when its gonna be complex and got executed frequently.

[Updated]

You can write the named queries at mapping, instead.

like image 36
Adeel Ansari Avatar answered Oct 07 '22 17:10

Adeel Ansari