代码之家  ›  专栏  ›  技术社区  ›  alexanoid

Spring Data/JPS(N+1)SELECT与OneToOne关联

  •  2
  • alexanoid  · 技术社区  · 9 年前

    在我的SpringData应用程序中,我遇到了(N+1)selects问题。

    我有以下Spring Data实体:

    @Entity
    @Table(name = "card_categories")
    public class CardCategory extends BaseEntity implements Serializable {
    
        @Id
        @SequenceGenerator(name = "card_categories_id_seq", sequenceName = "card_categories_id_seq", allocationSize = 1)
        @GeneratedValue(strategy = GenerationType.AUTO, generator = "card_categories_id_seq")
        private Long id;
    
        private String name;
    ...
    
    }
    
    @Entity
    @Table(name = "levels")
    public class Level extends BaseEntity implements Serializable {
    
        @Id
        @SequenceGenerator(name = "levels_id_seq", sequenceName = "levels_id_seq", allocationSize = 1)
        @GeneratedValue(strategy = GenerationType.AUTO, generator = "levels_id_seq")
        private Long id;
    
        private String name;
    ...
    }
    
    @Entity
    @Table(name = "card_categories_levels")
    public class CardCategoryLevel extends BaseEntity implements Serializable {
    
        @Id
        @SequenceGenerator(name = "card_categories_levels_id_seq", sequenceName = "card_categories_levels_id_seq", allocationSize = 1)
        @GeneratedValue(strategy = GenerationType.AUTO, generator = "card_categories_levels_id_seq")
        private Long id;
    
        @OneToOne
        @JoinColumn(name = "card_category_id")
        private CardCategory cardCategory;
    
        @OneToOne
        @JoinColumn(name = "level_id")
        private Level level;
    ...
    
    }
    

    和空的Spring Data存储库:

    @Repository
    public interface CardCategoryLevelRepository extends JpaRepository<CardCategoryLevel, Long> {
    }
    

    当我试图取回所有 CardCategoryLevel 实体 cardCategoryLevelRepository.findAll() 方法,它为我的每一行生成3个SELECT card_categories_levels 桌子

    为了使用一个JOIN而不是N+1个SELECT,我重新实现了 CardCategoryLevelRepository :

    @Repository
    public interface CardCategoryLevelRepository extends JpaRepository<CardCategoryLevel, Long> {
    
        @Query(value = "SELECT ccl FROM CardCategoryLevel ccl LEFT JOIN FETCH ccl.cardCategory cc LEFT JOIN FETCH ccl.level l where cc = :cardCategory and l = :level")
        CardCategoryLevel findByCardCategoryAndLevel(@Param("cardCategory") CardCategory cardCategory, @Param("level") Level level);
    
        @Override
        @Query(value = "SELECT ccl FROM CardCategoryLevel ccl LEFT JOIN FETCH ccl.cardCategory LEFT JOIN FETCH ccl.level")
        List<CardCategoryLevel> findAll();
    
    }
    

    但我不确定我是以正确的最佳方式完成的。

    请验证我的方法,并告诉它是解决(N+1)个SELECTs问题的最佳解决方法,Spring Data中是否存在OneToOne关联,以及最好的解决方法是什么。

    我是应该原封不动,还是应该转移到其他抽象……比如QueryDSL之类的?

    1 回复  |  直到 9 年前
        1
  •  1
  •   Community CDub    8 年前

    幸亏 Xtreme Biker 我用实体图和QueryDSL重新实现了我的解决方案