Hibernate 统计数据不涵盖 CrudRepository 中的 .save() 或 .deleteAll() 方法

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

我有一个 spring boot 应用程序,其中 spring data-jpa (v3.2.2) 在 java 17 上运行。

我已激活

generate_statistics
并配置了自定义
stats.factory
和自定义
session_factory.statement_inspector
来拦截正在调用的“任何”SQL 方法。

我试图获取有关应用程序及其运行时的所有 SQL 调用的一些额外信息,但统计 API 似乎不涵盖由 spring 预定义触发的插入/删除方法

.save()
.findById()来自 
.deleteAll()
CrudRepository
方法。请你解释一下为什么?

更具体地说:

我有 1 个实体:

@Entity
@NamedQueries(
        @NamedQuery(name="MyEntity.findByField2", query = "select e from MyEntity e where e.field2 = :someValue")
)
@Data
@ToString
@Table(name = "ent")
public class MyEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;

    @Version
    @Column(name = "version")
    private int version = 0;

    private String field1;

    private Integer field2;
}

1 个存储库:

@Repository
public interface MyEntityRepository extends CrudRepository<MyEntity, Long> {

    @Query("select e.id from MyEntity e where e.field1 = :someValue")
    public abstract List<Long> getIdsByField1(@Param("someValue") String someValue);

    @Query(value = "select field1 from ent where field2 = :someValue", nativeQuery = true)
    public abstract List<String> getField1ByField2(@Param("someValue") Integer someValue);

    public List<MyEntity> findByField2(@Param("someValue") Integer field2);

}

自定义报表检查器:

@Slf4j
public class SqlQueryInspector implements StatementInspector {

    @Override
    public String inspect(String s) {
        log.error("QUERY: {}", s);
        return s;
    }
}

以及

application.yaml
集中相应的设置:

spring.jpa.properties.hibernate.session_factory.statement_inspector=org.example.hibernate.SqlQueryInspector

自定义

StatisticsFactory
,创建自定义
StatisticsImpl

@Slf4j
public class CustomStatisticsFactory implements StatisticsFactory {
    @Override
    public StatisticsImplementor buildStatistics(SessionFactoryImplementor sessionFactory) {
        return new CustomStatisticsInitiator(sessionFactory);
    }
}

@Slf4j
public class CustomStatisticsInitiator extends StatisticsImpl {

    public CustomStatisticsInitiator(SessionFactoryImplementor sessionFactory) {
        super(sessionFactory);
    }

    @Override
    public void queryExecuted(String hql, int rows, long time) {
        log.info("########## [{}], [{}], [{}]", hql, rows, time);
        super.queryExecuted(hql, rows, time);
    }
}

application.yaml
中相应的属性:

spring.jpa.properties.hibernate.stats.factory=org.example.hibernate.CustomStatisticsFactory

我从存储库中调用以下方法:

repo.save(myEntity);
repo.getIdsByField1("someString");
repo.getField1ByField2(1);
repo.findByField2(2);
repo.findAll();
repo.findById(1L);
repo.deleteAll();

在运行时,当通过统计 API 请求统计数据时(请参阅下面使用的代码片段),我发现我只有 4 个

QueryStatistics
,相当于
findAll()
findByField2(int)
getIdsByField1(String)
getField1ByField2(int)
。但不适用于
save()
deleteAll()
findById
。但是
StatementInspector
会被所有查询调用(但它只包含 sql,而不包含时间)。为什么不是所有查询都通过统计 API 呈现?我如何也可以获得有关其他方法的信息?

获取统计数据代码:

SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
Statistics stats = sessionFactory.getStatistics();
String[] queries = stats.getQueries();
for (String query : queries) {
    QueryStatistics queryStats = stats.getQueryStatistics(query);
    // do something
}
java spring-boot hibernate statistics
1个回答
0
投票

懒惰测试

应用程序.属性

spring.jpa.show-sql=true
spring.jpa.hibernate.format_sql=true
spring.jpa.properties.hibernate.generate_statistics=true
logging.level.org.hibernate.stat=DEBUG

您的SpringBoot应用程序

import org.hibernate.SessionFactory;
import org.hibernate.stat.Statistics;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class YourApplication {

    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }

    @Bean
    public String showHibernateStatistics(SessionFactory sessionFactory) {
        Statistics statistics = sessionFactory.getStatistics();
        statistics.setStatisticsEnabled(true);
        new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(5000); // 5秒更新一次统计信息
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Create (save) count: " + statistics.getEntityInsertCount());
            }
        }).start();
        return "Hibernate statistics are now being displayed on console.";
    }
}

运行你的 Spring Boot,然后调用一些东西让你的应用程序保存一些实体。

您可以找到 Spring Boot 应用程序控制台输出:

Hibernate: insert into person (age,name,id) values (?,?,default) 
Create (save) count: 1

Statistics statistics = sessionFactory.getStatistics();

statistics.setStatisticsEnabled(true);

statistics.getEntityInsertCount());
<-- get Entity Insert count.

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