数据库查询一直是提升程序速度的瓶颈之一,本人也遇到了由于数据库数据查询太久致使影响失败,在这里记录如下解决的方法。数据库
该功能为统计功能,根据参数查找出符合的器具信息,而后再根据统计信息得出统计数据。就比如要统计某个年级学生的优秀,良好,及格率。看起来简单容易实现,可是到了测试环境中,却出现了错误:查询太久得不到响应。测试
通过打断点查看,发现系统问题出在了查询数据的过程当中。通过排查是数据过大,而且要链接的表过多,致使查询时间花费过大,前台得不到响应。hibernate
hibernate
在查询时,总会自动把全部关联的数据查询出来,而关联的数据又有关联的实体,这样同样致使要链接查询的表过多。就比如学生,教师,学院这三个实体:code
class Student { ...... @ManyToOne Teacher teacher; // 所属教师 @OneToOne Score score; // 所属成绩 } class Teacher { ...... @ManToOne College college; // 所属学院 } class College { ....... }
当统计学生成绩时,咱们并不须要教师的信息,可是hibernate
在查询时会自动来链接teacher表把教师的信息也查询出来,同时查询教师时还会链接学院表,把学院的数据也查询出来。这就致使了咱们须要为冗余的数据牺牲查询速度。因此解决的思路就是,在统计查询时,仅仅查询咱们须要的数据,不查询咱们不须要的数据。get
在复杂的查询中,每每须要许多关联的数据,能够经过自定义查询和投影的方式,实如今hibernate
中,仅仅查询本身想要的关联数据,提升查询速度。
在上面的例子中,咱们能够自定义查询:it
select name, score.score from student jion score on score.id=student.id where grade=2019
仅仅查询学生中的名字,学生成绩中的成绩两个信息,以后再经过投影,投影到实体上:io
public interface StudengtScoreProjections { String name; Double score; }
整合自定义查询和投影到仓库类中:class
public interface StudentRepository extends CrudRepository<Student, Long> { @Query(value = "select name, score.score as score from student jion score s on score.id=student.id where grade=?1) ",nativeQuery = true) List<StudengtScoreProjections> getAllByGrade(Long grade); }
为了复用查询,能够创建响应的视图,查询时从视图中查询:List
// 数据库创建视图 create view student_score as select name, score.score as score,grade from student jion score s on score.id=student.id // 仓库类中改成从视图中查询 public interface StudentRepository extends CrudRepository<Student, Long> { @Query(value = "select * from student_score where grade=?1) ",nativeQuery = true) List<StudengtScoreProjections> getAllByGrade(Long grade); }
再创建投影和实体之间的转换方法,达到查询的目的。select
经过自定义查询和投影的方法,来解决hibernate
自动查询关联数据的问题,使用自定义的查询,能够提升数据库查询的灵活性和速度。