Hibernate查询计数

4
有没有办法在事务或线程中统计Hibernate内部执行的查询次数?我研究了Hibernate拦截器,但不清楚应该覆盖哪些API来增加计数器。我的目标是构建一个警报,当某个请求的查询次数超过某个阈值时通知我,以便我可以根据需要进行优化。
谢谢,
Sam
3个回答

4
这个问题很老了,但我认为它可以帮助其他人。
库Spring Hibernate Query Utils (https://github.com/yannbriancon/spring-hibernate-query-utils)提供了一个每个线程的查询计数器,可用于集成测试中检查每个请求生成的查询数量。
README中有一个示例:
...
import com.yannbriancon.interceptor.HibernateQueryInterceptor;


@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class NotificationResourceIntTest {
    @Autowired
    private HibernateQueryInterceptor hibernateQueryInterceptor;

    @Test
    public void saveFile_isOk() throws Exception {
        // Initialize the query to 0 and allow the counting
        hibernateQueryInterceptor.startQueryCount();

        // Call the resource that we want to test
        MvcResult result = mvc.perform(get("/rest/notifications"))
                .andExpect(status().isOk())
                .andReturn();

        // Get the query count for this thread and check that it is equal to the number of query you expect, let's say 4.
        // The count is checked and we detect potential n+1 queries.
        Assertions.assertThat(hibernateQueryInterceptor.getQueryCount()).isEqualTo(4);
    }
 }


2
这篇文章是否对您有帮助? http://www.javalobby.org/java/forums/t19807.html 你可以这样做:
SessionFactory sessionFactory = getSessionFactoryForApplication();
Statistics stats = sessionFactory.getStatistics();
stats.setStatisticsEnabled(true);

// All of the queries that have executed.
String[] queries = stats.getQueries();

And so on...


1
如果有10个请求同时到达,每个请求都在自己的事务或线程中运行。我能否查询每个请求的查询计数?还是它们全部混合在一起了? - Sam Lai
它们都混合在一个单一的SessionFactory中(通常每个应用程序只有一个)。您应该探索统计API,其中有一个名为getQueryStatistics(String queryString)的方法,这可能是您想要的。 - MrJames
第三行(setStatisticsEnabled)真的帮了我很多。谢谢。 - Roeniss

0
我写了一个小型库(https://github.com/Lemick/hibernate-query-asserts),可以在你的Spring测试中断言Hibernate生成的SQL查询类型(SELECT,INSERT等)的数量,这样,每当测试中的SQL语句发生变化时,你就会收到警告,并防止N+1选择。如果您想了解如何实现此操作,请在此处查看该项目。
下面是一个演示目的的测试示例:
@Test
@AssertHibernateSQLCount(inserts = 1)
void create_one_entity_from_endpoint() {
    BlogPost requestBody = new BlogPost("My new blog post");

    BlogPost responseBody = restTemplate.postForObject("/blogPosts", requestBody, BlogPost.class);

    assertEquals("My new blog post", responseBody.getTitle(), "The blog post created is returned");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接