在Spring Data Query中过滤子对象

时间:2014-10-31 22:30:41

标签: java spring spring-data spring-data-jpa

我有以下域名模型:

Playlist - &gt; List<PlaylistItem> - &gt; 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
}

我的存储库:

public interface PlaylistRepository extends JpaRepository<Playlist, Long> {
   List<Playlist> findAll();
}

现在,如何返回仅包含现有视频的播放列表,即如果数据库中有三个视频分配给该播放列表项目,其中一个视频的isDeleted设置为true,那么我只需要获取两个项目代替。

4 个答案:

答案 0 :(得分:11)

您所要做的就是在PlaylistRepository界面上声明此方法:

List<Playlist> findByPlaylistItemsVideoIsDeleted(boolean isDeleted);

并称之为:

playListRepository.findByPlaylistItemsVideoIsDeleted(false);

这将返回包含未删除视频的所有播放列表。

答案 1 :(得分:5)

Maksim,您可以使用 @query 这样的注释:

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();
}

甚至更好的方式:

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);
}

答案 2 :(得分:3)

您可以查看Spring数据规范。您可以通过调用repository.findAll(s);

来使用它们

规范允许您在查询中添加任意条件,包括要添加的过滤器。规格的另一个好处是它们可以是类型安全的。见这里:

http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#specifications

答案 3 :(得分:0)

您可能已经解决了此问题,但我想我会为此提供帮助,希望它可以对您或其他访问此页面的人有所帮助。

使用Spring JPA规范,您将:

  1. 启用PlaylistRepository以使用JPA规范
  2. Specification写为可重用的方法
  3. 使用Specification作为查询

这是详细信息。

1。实施JpaSpecificationExecutor

更新PlaylistRepository以实现JpaSpecificationExecutor。这会将find*个接受Specification<T>参数的方法添加到您的PlaylistRepository中。

public interface PlaylistRepository extends JpaRepository<Playlist, Long>, 
            JpaSpecificationExecutor<Playlist> {

}

2。创建Specification

使用静态方法创建一个类,以用于创建可重用 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);
        };
    }
}

使用root.join(及随后的join)与在SQL中使用JOIN相似。在这里,我们在类的字段上联接,而不是在表的列上联接。

3。发出查询

我不知道您打算如何发布查询,但是下面是在“服务”类中如何进行查询的示例:

@Service
public class PlaylistService {

    @Autowired
    private PlaylistRepository playlistRepository;

    public List<Playlist> findPlaylistsWithExistingVideos() {

        Specification<Playlist> spec = PlaylistSpecifications.hasExistingVideos();
        return playlistRepository.findAll(spec);
    }
}

希望这会有所帮助!