It is my first experience with JPA-Specification
.
I tried to implement a sample project with same requirements of my real project.
Here Are my Entities: Movie
and Actor
@Entity
@Table(name = "MOVIE")
public class Movie {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private Long id;
@Column(name = "TITLE")
@Basic
private String title;
@Column(name = "GENRE")
@Basic
private String genre;
@Column(name = "RATING")
@Basic
private double rating;
@Column(name = "WATCH_TIME")
@Basic
private double watchTime;
@Column(name = "RELEASE_YEAR")
@Basic
private int releaseYear;
}
@Entity
@Table(name = "ACTOR")
public class Actor {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private Long id;
@Column(name = "NAME")
@Basic
private String name;
@Column(name = "FAMILY")
@Basic
private String family;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "MOVIE_ID")
@Fetch(FetchMode.JOIN)
private Movie movie;
@Basic
@Column(name = "DATE_TIME")
private Timestamp dateTime;
}
Also I have their repositories which extends JpaSpecificationExecutor<>
And my ActorSpecification
is as below:
public class ActorSpecification implements Specification<Actor> {
private List<SearchCriteria> list;
public ActorSpecification() {
this.list = new ArrayList<>();
}
public void add(SearchCriteria criteria) {
list.add(criteria);
}
@Override
public Predicate toPredicate(Root<Actor> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
//create a new predicate list
List<Predicate> predicates = new ArrayList<>();
//add criteria to predicates
for (SearchCriteria criteria : list) {
Join<Actor, Movie> join = root.join(Actor_.MOVIE);
query.orderBy(builder.desc(root.get(Actor_.DATE_TIME)));
if (criteria.getOperation().equals(SearchOperation.IN_MOVIE_ID)) {
predicates.add(join.get(Movie_.ID).in(Arrays.asList(72, 74, 76, 78)));
} else if (criteria.getOperation().equals(SearchOperation.IN_MOVIE_WATCHTIME)) {
predicates.add(join.get(Movie_.WATCH_TIME).in(Arrays.asList(135, 126)));
}
}
return builder.and(predicates.toArray(new Predicate[0]));
}
}
And this is the way I use to filter my data and fetch data:
ActorSpecification actorsInMovieIdList = new ActorSpecification();
actorsInMovieIdList.add(new SearchCriteria("MovieId", "72, 74, 76, 78", SearchOperation.IN_MOVIE_ID));
List<Actor> actorsMovieIdList = actorRepository.findAll(actorsInMovieIdList);
ActorSpecification actorsInMovieWatchTime = new ActorSpecification();
actorsInMovieWatchTime.add(new SearchCriteria("MovieWatchTime", "135 ,126", SearchOperation.IN_MOVIE_WATCHTIME));
List<Actor> actorsMoviesWatchTime = actorRepository.findAll(actorsInMovieIdList.and(actorsInMovieWatchTime));
AND NOW MY REQUIREMENT:
As we have many Actor
in each Movie
, so the join result will return list of Actors of each movie that matches our conditions for filtering movies.
Now I need to just return the Actor of that movie which has the greatest DATE_TIME
,is there any way for doing it with JpaSpecification
or I need to implement a filter method myself.
If I want to tell you about my real project in order to make it more clear.
I have STOCK
and DAILY_PRICE
Tables and of course any Stock has many Daily_Price, So I just want to fetch the last Daily_price joining my Stock record.
Can anyone help me in this issue??
Any help will be appreciated!!