Reputation: 7561
I have an usual Spring Data JPA repository in my spring project.
@Repository
public interface EventRepository extends CrudRepository<Event, Long> {
List<Event> findByOriginalIdIn(Collection<String> originalEventIds);
...
I used before method findByOriginalIdIn
it was working good. But situation is changed and I need to handle same request using collection of pairs to find and filter correct events.
My alternative method should Handle next logic:
find by (originalId1 AND originalCalendarId1) OR (originalId2 AND originalCalendarId2) OR (originalId..N AND originalCalendarId..N) OR
Is it possible handle this request using Selectively exposing CRUD methods? If yes, could I have an example please?
Upvotes: 3
Views: 6568
Reputation: 1097
To not create custom repository I'd recommend to use Spring Data JPA specifications. Here's an draft example.
class Specification1 implements Specification<Event> {
private final List<Pair<String, String>> pairs;
public Specification1(List<Pair<String, String>> pairs) {
this.paris = pairs;
}
@Override
public Predicate toPredicate(Root<Event> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate[] as = pairs.stream().map(pair -> {
return cb.and(cb.equal(root.get("originalId2"), pair.getKey())),cb.equal(root.get("originalCalendarId2"), pair.getKey());
}).toArray(Predicate[]::new);
return cb.or(as);
}
}
userRepository.findAll(new Specification1(...));
In additional you repository has to extend JpaSpecificationExecutor.
Upvotes: 1
Reputation: 1136
I would suggest using QueryDSL with Spring JPA to make your implementation in easy manner.
With QueryDSL, you could easily construct your predicate (nothing but the criteria) and use it in the query. In your case, it would probably be something like below. Please refer to the link: Spring Data JPA Tutorial: Creating Database Queries With Querydsl on how to use QueryDSL with Spring Data JPA.
In your case, for given condition,
find by (originalId1 AND originalCalendarId1) OR (originalId2 AND originalCalendarId2) OR (originalId..N AND originalCalendarId..N) OR
I did not understand if e.g. originalId1/originalCalendarId1 should be equal to any value. Let's say, for the sake of simplicity and explanation, they are to be equal to some value.
import com.mysema.query.BooleanBuilder;
import com.mysema.query.types.Predicate;
public class EventPredicates {
public static Predicate getAllEventsByOrginalIds(String[] originalIds, String[] originalCalendarIds) {
QEvent event = QEventEntity.event;
BooleanBuilder builder = new BooleanBuilder();
//assuming both arrays are of same size.
for (int idx = 0; idx < originalIds.length; idx++) {
builder.or(event.originalIds[0].eq.(someValue)).and(event.originalCalendarIds[0].eq.(someCalValue));
}
return builder;
}
}
However, your repository interface should extend QueryDslPredicateExecutor<Event>
to make use of the QueryDSL functionality.
In your service method, you could make the call something like below assuming EventRepository is declared as below:
@Autowired
EventRepository eventRepository;
public void someMethod(){
...
List<Events> events = eventRepository.findAll(EventPredicates.getAllEventsByOrginalIds(originalIdsArr, originalCalendarIdsArr));
...
}
Btw, QueryDSL makes it very easy to implement different criteria (simple to complex). Refer to the above link on how to use it.
Hope this helps.
Upvotes: 0
Reputation: 83
Try to use criteria with following restrictions:
Criteria criteria = session.createCriteria(Event.class)
.add(Restrictions.in("id", values));
Upvotes: 0