Best Practices for Using Querydsl with Spring Data

Using Spring Data nad Querydsl, we can simply declare the repository interface and skip the implementation class. Some methods with a specific name or using the @Query annotation and all.

But sometimes I would like to use JPAQuery and define the method body myself, say

@Repository public class MyRepositoryImpl implements MyRepository { @PersistenceContext private EntityManager em; @Override public List<Tuple> someMethod(String arg) { JPAQuery query = new JPAQuery(em); ... } 

but in this way I will have to implement other methods of the MyRepository interface that destroy all the benefits of Spring Data!

I see two options:

  • Declare a different interface for each repository and then execute it (which doubles the number of interfaces)
  • Introduce EntityManager into the @Service class and implement my own methods there

I like option # 2, but as far as I know, in the @Service class we should only call repository methods, so this is also not an ideal solution.

So how do programmers deal with this?

+7
spring spring-data spring-data-jpa querydsl
source share
2 answers

You should not implement the actual Spring data repository, instead you should declare a different user interface where you can put your own methods.

Say you have a MyRepository defined as

 @Repository public interface MyRepository extends JpaRepository<Tuple, Long> {} 

Now you want to add your own findTuplesByMyArg() , for which you need to create a repository user interface

 public interface MyRepositoryCustom { List<Tuple> findTuplesByMyArg(String myArg); } 

Then comes the implementation of the user interface

 public class MyRepositoryImpl implements MyRepositoryCustom { @PersistenceContext private EntityManager em; @Override public List<Tuple> findTuplesByMyArg(String myArg) { JPAQuery query = new JPAQuery(em); ... } } 

And we need to change the MyRepository , so it expands the user repository, therefore

 @Repository public interface MyRepository extends JpaRepository<Tuple, Long>, MyRepositoryCustom {} 

And you can easily access findTuplesByMyArg() by entering MyRepository , for example.

 @Service public class MyService { @Autowired private MyRepository myRepository; public List<Tuple> retrieveTuples(String myArg) { return myRepository.findTuplesByMyArg(myArg); } } 

Note that the names here are important (you need to have the Impl default postfix configs in the repo implementation).

You can find all the necessary information here.

+8
source share

I would suggest a small correction to the answer above, which is trying to use JPAQueryFactory. It is good to use the provided factory class.

 public class MyRepositoryImpl implements MyRepositoryCustom { @Autowired private JPAQueryFactory factory; @Override public List<Tuple> findTuplesByMyArg(String myArg) { JPAQuery query = factory.query(); ... }} @Configuration public class Config { @Autowired private EntityManager em; @Bean public JPAQueryFactory jpaQueryFactory() { return new JPAQueryFactory(em); } } 
+1
source share

All Articles