如何通过单个查询 select 不相关的实体

How to select unrelated entities with a single query

假设我们有 5 个 table,它们彼此之间没有任何关系,但它们都共享同一列。我们将 table 命名为 ClojureConfKotlinConfScalaConfGroovyConfJavaConf。他们都有一列UserId。其他列的数量和数据类型各不相同。给定用户可能参加了零个或多个会议。

任务只是 select 给定 UserId 的 5 table 中每一个的所有记录,将它们转换为 DTO,并将 return 作为 json。

目前,代码对数据库进行了 5 次访问,以从每个 table.

中获取结果列表

hibernate/jpa 中是否有库支持,什么可以单次访问数据库?目标是提高性能。

是否可以为看起来类似于此的实体定义投影:

interface ConfAttended {

    List<ClojureConf> getClojureConfs();
    List<KotlinConf> getKotlinConfs();
    List<ScalaConf> getScalaConfs();
    List<GroovyConf> getGroovyConfs();
    List<JavaConf> getJavaConfs();

}

和一个可以 select 并一次性映射结果的存储库

interface ConfAttendedDAO extends JpaRepository<User, Long> {

    @Query("SELECT c, k, s, g, j FROM ClojureConf c " +
            "JOIN KotlinConf k ON c.UserId = k.UserId " +
            "JOIN ScalaConf s ON c.UserId = s.UserId " +
            "JOIN GroovyConf g ON c.UserId = g.UserId " +
            "JOIN JavaConf j ON c.UserId = j.UserId " +
            "WHERE c.UserId = :userId")
    ConfAttended findByUserIdForProjection(@Param("userId") long userId);

}

?

我最终遇到了这样的查询:

interface ConfAttendedDAO extends JpaRepository<User, Long> {

    @Query("SELECT c, k, s, g, j FROM User u " +
            "LEFT JOIN ClojureConf c ON c.UserId = :userId " +
            "LEFT JOIN KotlinConf k ON k.UserId = :userId " +
            "LEFT JOIN ScalaConf s ON s.UserId = :userId " +
            "LEFT JOIN GroovyConf g ON g.UserId = :userId " +
            "LEFT JOIN JavaConf j ON j.UserId = :userId " +
            "WHERE u.Id = :userId")
    List<Object[]> findAllByUserId(@Param("userId") long userId);

}

Hibernate 负责将行映射到实体。每个 Object[] 都将所有 5 个实体(或空值)作为其元素。从 User 中选择是强制查询到 return 个结果。否则,如果第一个 table return 什么都没有 - 整个查询 return 什么都没有。另一个缺点是,如果一个 table 有 10 个结果而另一个有 1 个,则结果较少的 table 会使它们重复。

至于性能(做这一切的唯一意义),获取和处理结果比 5 个单独的 SELECTs 快 4-5 倍。