Hibernate 统计信息未按预期计算 queryExecutionCount

问题描述 投票:0回答:1

通过我的代码,我在实体之间的多对一关系中强制执行 n + 1 问题。 为了检查是否存在 n + 1 问题,我设置了一个测试。

运行测试时,我还可以看到执行了 3 个查询,但休眠统计信息仍然返回 1 个已执行的查询。这显然是错误的。

在我的测试中刷新并清除实体管理器也应该可以防止缓存问题。

这是测试的日志:

Hibernate: insert into shelter (name,id) values (?,default)
Hibernate: insert into shelter (name,id) values (?,default)
Hibernate: insert into messages (name,shelter_id,id) values (?,?,default)
Hibernate: insert into messages (name,shelter_id,id) values (?,?,default)
Hibernate: insert into messages (name,shelter_id,id) values (?,?,default)
Hibernate: select a1_0.id,a1_0.name,a1_0.shelter_id from messages a1_0
Hibernate: select s1_0.id,s1_0.name from shelter s1_0 where s1_0.id=?
Hibernate: select s1_0.id,s1_0.name from shelter s1_0 where s1_0.id=?
Hibernate: drop table if exists messages cascade

这是我的代码:

实体一:

@Entity
@Table(name = "messages")
data class Animal(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0,

    @Column(nullable = false)
    val name: String,

    @ManyToOne
    @JoinColumn(name = "shelter_id")
    val shelter: Shelter
)

实体二:

@Entity
@Table(name = "shelter")
data class Shelter(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0,

    @Column(nullable = false)
    val name: String,
)

存储库:

@Repository
interface AnimalRepository: JpaRepository<Animal, Long> {}

存储库测试:

@DataJpaTest
class AnimalRepositoryTest @Autowired constructor(
    private val animalRepository: AnimalRepository,
    private val entityManager: EntityManager
) {
    private lateinit var hibernateStatistics: Statistics

    @BeforeEach
    fun setUp() {
//        // Initialize the Hibernate statistics
        val sessionFactory = entityManager.unwrap(Session::class.java).sessionFactory
        hibernateStatistics = sessionFactory.statistics
        hibernateStatistics.isStatisticsEnabled = true
        hibernateStatistics.clear()  // Reset statistics before each test

        // Insert initial test data
        val shelter = Shelter(name = "Happy Shelter")
        val shelter2 = Shelter(name = "Happy Shelter2")
        entityManager.persist(shelter)
        entityManager.persist(shelter2)

        val animal1 = Animal(name = "Lion", shelter = shelter)
        val animal2 = Animal(name = "Tiger", shelter = shelter)
        val animal3 = Animal(name = "Panda", shelter = shelter2)
        entityManager.persist(animal1)
        entityManager.persist(animal2)
        entityManager.persist(animal3)

        entityManager.flush()
        entityManager.clear()  // Clear persistence context to ensure fresh retrieval
    }

    @Test
    @Transactional
    @Rollback
    fun `should execute one SQL query when finding all animals with shelter`() {
        // Perform the operation (fetch all animals with shelter)
        val animals = animalRepository.findAll()

        // Assert the result
        assertThat(animals).hasSize(3)
        animals.forEach { animal -> animal.shelter.name}

        // Check Hibernate statistics for SQL query count
        val executedQueryCount = hibernateStatistics.queryExecutionCount
        assertThat(executedQueryCount).isEqualTo(1)
    }
}

如果您需要更多信息,请告诉我;)

spring kotlin hibernate spring-data-jpa
1个回答
0
投票

Hibernate 统计信息不将获取单个实体视为查询,而是将其视为加载的实体。您可以将

.findAll()
替换为
.findById(1)
,并且
hibernateStatistics.queryExecutionCount
将为 0。要查看已加载实体的数量,请检查
hibernateStatistics.entityLoadCount

© www.soinside.com 2019 - 2024. All rights reserved.