Reputation: 2119
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
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
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