pzeszko
pzeszko

Reputation: 2119

Best practise when using Querydsl with Spring Data

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

But sometimes I'd like to use JPAQuery and define method's body by myself, let's say

@Repository
public class MyRepositoryImpl implements MyRepository {

    @PersistenceContext
    private EntityManager em;

    @Override
    public List<Tuple> someMethod(String arg) {
        JPAQuery query = new JPAQuery(em);
        ...
    }

but this way I would have to implement other MyRepository interface methods, which ruins all Spring Data's advantages!

I can see two options:

I like option #2 more, but as far I as know, in @Service class we should only call repository methods, so it's not a perfect solution as well.

So how does programmers deal with it?

Upvotes: 16

Views: 8391

Answers (2)

vtor
vtor

Reputation: 9319

You should not implement the actual Spring Data repository, instead you have to declare another custom interface where you can put your custom methods.

Let's say you have a MyRepository, defined as

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

Now you want to add your custom findTuplesByMyArg(), for a sake of purpose you need to create custom repository interface

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

Afterwards comes the implementation of custom interface

public class MyRepositoryCustomImpl implements MyRepositoryCustom {
    @PersistenceContext
    private EntityManager em;

    @Override
    public List<Tuple> findTuplesByMyArg(String myArg) {
        JPAQuery query = new JPAQuery(em);
        ...
    }    
}

And we need to change MyRepository declaration, so it extends custom repository, so that

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

And you can easily access your findTuplesByMyArg() by injecting MyRepository, e.g.

@Service
public class MyService {
   @Autowired
   private MyRepository myRepository;

   public List<Tuple> retrieveTuples(String myArg) { 
      return myRepository.findTuplesByMyArg(myArg);
   }
}

Pay attention that names are important here (you need to have Impl postfix by default configs in repo implementation).

You can find all needed information here

Upvotes: 22

Vaibhav Bansal
Vaibhav Bansal

Reputation: 137

I would suggest a minor rectification to the answer above, which tries to use JPAQueryFactory. It is good to make use of 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);
}

}

Upvotes: 10

Related Questions