Spring Data/JPS (N+1) 具有 OneToOne 关联的 SELECT
Spring Data/JPS (N+1) SELECTs with OneToOne associations
在我的Spring数据应用中我运行进入(N+1)选择问题。
我有以下 Spring 个数据实体:
@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 数据存储库:
@Repository
public interface CardCategoryLevelRepository extends JpaRepository<CardCategoryLevel, Long> {
}
当我尝试通过 cardCategoryLevelRepository.findAll()
方法获取所有 CardCategoryLevel
实体时,它会为我的 card_categories_levels
table.
中的每一行生成 3 个 SELECT
为了使用一个 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();
}
但我不确定我是否以正确的最佳方式做到了。
请验证我的方法并告诉它是解决 Spring 数据中 OneToOne 关联的 (N+1) SELECT 问题的最佳解决方法,以及解决它的最佳方法是什么。
我应该保持原样还是可以转移到其他抽象.. 例如像 QueryDSL 或类似的东西?
感谢 Xtreme Biker 我用实体图和 QueryDSL 重新实现了我的解决方案
在我的Spring数据应用中我运行进入(N+1)选择问题。
我有以下 Spring 个数据实体:
@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 数据存储库:
@Repository
public interface CardCategoryLevelRepository extends JpaRepository<CardCategoryLevel, Long> {
}
当我尝试通过 cardCategoryLevelRepository.findAll()
方法获取所有 CardCategoryLevel
实体时,它会为我的 card_categories_levels
table.
为了使用一个 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();
}
但我不确定我是否以正确的最佳方式做到了。
请验证我的方法并告诉它是解决 Spring 数据中 OneToOne 关联的 (N+1) SELECT 问题的最佳解决方法,以及解决它的最佳方法是什么。
我应该保持原样还是可以转移到其他抽象.. 例如像 QueryDSL 或类似的东西?
感谢 Xtreme Biker 我用实体图和 QueryDSL 重新实现了我的解决方案