让我们想象一下,我们有5个表,彼此之间没有关系,但是它们共享同一列。我们将表命名为ClojureConf
,KotlinConf
,ScalaConf
,GroovyConf
,JavaConf
。它们都有一列UserId
。其他各列的数量和数据类型各不相同。给定的用户可能参加了零个或多个会议。
任务是从给定的UserId
的5个表中的每个表中选择所有记录,将它们转换为DTO并以json的形式返回。
当前,代码执行5次访问数据库的操作,以获取每个表的结果列表。
hibernate / jpa中是否有库支持,一次访问数据库的原因是什么?目标是提高性能。
是否可以为看起来与此相似的实体定义投影:
interface ConfAttended {
List<ClojureConf> getClojureConfs();
List<KotlinConf> getKotlinConfs();
List<ScalaConf> getScalaConfs();
List<GroovyConf> getGroovyConfs();
List<JavaConf> getJavaConfs();
}
和一个可以一次性选择和映射结果的存储库
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);
}
?
答案 0 :(得分:2)
我最终遇到了这样的查询:
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个实体(或null)作为其元素。从User
中进行选择将强制查询返回结果。否则,如果第一个表什么都不返回-整个查询什么也不返回。另一个缺点是,如果一个表有10个结果,而另一个表有1个,则结果较少的表会使它们重复。
关于性能(这样做的唯一目的),获得和处理结果的速度比5个单独的SELECT
快4-5倍。