如何在最小查询次数中获取所有多对多关系?

时间:2016-04-20 15:48:05

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

如何使用最少量的查询获取所有多对多关系? 我的意思是没有任何n+1 queries。 3 - 这是正常的

我有一个实体:

@Entity
@Table(name = "tags")
public class Tag {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Column(name = "title")
    private String title;
}

@Entity
@Table(name = "stations")
public class Station {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Column(name = "title")
    private String title;
}

@Entity
@Table(name = "songs")
public class Song {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @Column(name = "title")
    private String title;

    @ManyToMany
    @JoinTable(
            name = "songs_stations",
            joinColumns = {
                    @JoinColumn(
                            name = "song_id",
                            referencedColumnName = "id"
                    )
            },
            inverseJoinColumns = {
                    @JoinColumn(
                            name = "station_id",
                            referencedColumnName = "id"
                    )
            }
    )
    private List<Station> stations;

    @ManyToMany
    @JoinTable(
            name = "songs_tags",
            joinColumns = {
                    @JoinColumn(
                            name = "song_id",
                            referencedColumnName = "id"
                    )
            },
            inverseJoinColumns = {
                    @JoinColumn(
                            name = "tag_id",
                            referencedColumnName = "id"
                    )
            }
    )
    private List<Tag> tags;
}

还有一个存储库:

public interface SongRepository extends CrudRepository<Song, Long> {

    @Query("SELECT s FROM Song s LEFT JOIN FETCH s.tags LEFT JOIN FETCH s.stations")
    public List<Song> completeFindAllSongs();
}
  • 所以,我无法在completeFindAllSongs() cannot simultaneously fetch multiple bags @NamedEntityGraph songs_tags原因中使用预先加载
  • 无法使用@LazyCollection
  • 我无法手动加载数据,因为我无法访问query
  • 请不要建议使用optionalWords

我该怎么办?

2 个答案:

答案 0 :(得分:2)

  

所以,我不能在completeFindAllSongs()中使用急切加载导致无法同时获取多个包

如果您将实体更改为使用“Set”而不是OneToMany和ManyToMany关系的“List”,则此错误应该消失。

编辑:所以回答你的问题是:你只需要1个查询。只需使用集合和渴望获取任何你想要的东西。

答案 1 :(得分:1)

请记住,通过连接获取多个集合,您将在集合行之间创建完整的笛卡尔积,这可能会对数据库和应用程序端产生巨大的负面性能影响。

您可能需要考虑使用batch size批量初始化集合。