I have a following domain model:
Playlist -> List<PlaylistItem> -> Video
@Entity
class Playlist{
   // id, name, etc
   List<PlaylistItem> playlistItems;
   // getters and setters
}
@Entity
class PlaylistItem{
   // id, name, etc.
   Video video;
   // getters and setters
}
@Entity
class Video{
   // id, name, etc.
   boolean isDeleted;
   // getters and setters
}
And my repository:
public interface PlaylistRepository extends JpaRepository<Playlist, Long> {
   List<Playlist> findAll();
}
Now, how do I return a playlist with only existing videos, ie, if there are three videos in the database assigned to that playlist item and one of those videos has isDeleted set to true, then I need to get only two items instead.
All you have to do is declare this method on your PlaylistRepository interface:
List<Playlist> findByPlaylistItemsVideoIsDeleted(boolean isDeleted);
And call it like this:
playListRepository.findByPlaylistItemsVideoIsDeleted(false);
That will return all playlist with videos that are not removed.
Maksim, you could use the @query annotation like this :
public interface PlaylistRepository extends JpaRepository<Playlist, Long> {
   @Query("select playlist from Playlist playlist 
           fetch join playlist.playlistItems itens
           fetch join itens.video as video
           where video.isDeleted = false")
   List<Playlist> findAll();
}
Or even better way :
public interface PlaylistRepository extends JpaRepository<Playlist, Long> {
   @Query("select playlist from Playlist playlist 
           fetch join playlist.playlistItems itens
           fetch join itens.video as video
           where video.isDeleted = :hasVideo ")
   List<Playlist> findPlayList(@Param("hasVideo") boolean hasVideo);
}
                        You may have already resolved this issue, but I thought I would contribute this in hopes it might help you, or anyone else visiting this page.
Using Spring JPA Specifications, you would:
PlaylistRepository to use JPA SpecificationsSpecification as a reusable methodSpecification as the queryHere are the details.
JpaSpecificationExecutor
Update PlaylistRepository to implement JpaSpecificationExecutor.  This adds find* methods that accept Specification<T> parameters to your PlaylistRepository.
public interface PlaylistRepository extends JpaRepository<Playlist, Long>, 
            JpaSpecificationExecutor<Playlist> {
}
Specification
Create a class with a static method for use in creating a reusable Specification.
public final class PlaylistSpecifications {
    private PlaylistSpecifications() {}
    public static Specification<Playlist> hasExistingVideos() {
        return (root, query, cb) -> {
            return cb.equal(root.join("playlistItems").join("video")
                    .get("isDeleted"), false);
        };
    }
}
Using root.join (and subsequent joins) is similar to using JOIN in SQL.  Here, we are joining on the fields of classes, instead of on columns of tables.
I don't know how you plan to issue your query, but below is an example of how it could be done in a "service" class:
@Service
public class PlaylistService {
    @Autowired
    private PlaylistRepository playlistRepository;
    public List<Playlist> findPlaylistsWithExistingVideos() {
        Specification<Playlist> spec = PlaylistSpecifications.hasExistingVideos();
        return playlistRepository.findAll(spec);
    }
}
Hope this helps!
You can look into Spring Data Specifications. You use them by calling repository.findAll(s);
Specifications allow you add on arbitrary conditions to your query, including the filter you want to add. Another nice thing about Specifications is that they can be type-safe. See here:
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#specifications
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With