Java 如何在一个JDBC连接中执行多个JPA查询

Java 如何在一个JDBC连接中执行多个JPA查询,java,hibernate,spring-boot,jpa,connection-pool,Java,Hibernate,Spring Boot,Jpa,Connection Pool,在Spring引导应用程序中,我将JPA与Hibernate结合使用 我有一个自定义的select查询方法,在JPA存储库中定义了参数化IN子句。由于数据量巨大,我使用作为参数传递的小批量ID多次执行同一查询。但我无法提高性能 大约有200000条记录,耗时1分钟。这是非常巨大的 下面是我最累的事情 只选择所需的列,而不是整个POJO->将查询时间减少了8秒 当我分析Hibernate静态时:以下是找到的日志: 382016470纳秒用于获取1个JDBC连接; 释放0个JDBC连接花费0纳秒;

在Spring引导应用程序中,我将JPA与Hibernate结合使用

我有一个自定义的select查询方法,在JPA存储库中定义了参数化IN子句。由于数据量巨大,我使用作为参数传递的小批量ID多次执行同一查询。但我无法提高性能

大约有200000条记录,耗时1分钟。这是非常巨大的

下面是我最累的事情

只选择所需的列,而不是整个POJO->将查询时间减少了8秒 当我分析Hibernate静态时:以下是找到的日志:

382016470纳秒用于获取1个JDBC连接; 释放0个JDBC连接花费0纳秒; 798909958纳秒用于准备1条JDBC语句; 305523944纳秒用于执行1条JDBC语句; 执行0个JDBC批处理花费0纳秒; 执行0次L2C puts所花费的0纳秒; 0纳秒执行0次L2C点击; 0纳秒用于执行0次L2C未命中; 0纳秒用于执行0次刷新,总共刷新0个实体和0个集合; 0纳秒用于执行0次部分刷新,总共刷新0个实体和0个集合

即使使用Hikari连接池,创建JDBC连接也需要时间。以下是hikari属性

 spring.datasource.hikari.connection-timeout=120000
    spring.datasource.hikari.maximum-pool-size=100
    spring.datasource.hikari.minimum-idle=30
 spring.jpa.hibernate.connection.provider_class=org.hibernate.hikaricp.internal.HikariCPConnectionProvider
    spring.datasource.hikari.pool-name=HikariConnectionPool
    spring.datasource.hikari.data-source-properties.cachePrepStmts=true
    spring.datasource.hikari.data-source-properties.useServerPrepStmts=true
并为每个jpa查询建立、准备JDBC连接。 即使在设置了以下属性之后

 spring.datasource.hikari.connection-timeout=120000
    spring.datasource.hikari.maximum-pool-size=100
    spring.datasource.hikari.minimum-idle=30
 spring.jpa.hibernate.connection.provider_class=org.hibernate.hikaricp.internal.HikariCPConnectionProvider
    spring.datasource.hikari.pool-name=HikariConnectionPool
    spring.datasource.hikari.data-source-properties.cachePrepStmts=true
    spring.datasource.hikari.data-source-properties.useServerPrepStmts=true
spring.datasource.hikari.datasourceproperties.cacheprepsmts=true spring.datasource.hikari.datasourceproperties.UseServerPrepsmts=true

我保持IN子句的参数数量不变

代码Snippnet

//JPA Reposistry

public interface CarRepository extends CrudRepository<Car, String>, JpaSpecificationExecutor<Car> {

@Query(SELECT u.carName as carName,
    u.carId as
    carId from
    Car u
    where u.carId in (:carIds))
List<CarP> findCarProjections@Param("carIds")Set<String> carIds);

}

//Service
    @Component public carService

{
@Autowired
CarRepository carRepo;

public void processCars(List<carId> carIds)
{

List<List<String>> carIdPartioned = partionCarIds(carIds)
ExecutorService es = Executors.newFixedThreadPool(10);
for(List<String> carIdPart : carIdPartioned)
es.submit(new ProcessCarInThread(carIdPart,carRepo));

}

//Each Call Creates a new connection to JDBC 
//Takes time to prepare Statement ( as given in hibernate statics )
class ProcessCarInThread implements Runnable
{
List<String> carIds;
CarRepository carRepo;
public ProcessCarInThread(List<String> carIds, CarRepository carRepo )
{
this.carIds=carIds;
this.carRepo=carRepo;
}
       @Override
    public void run() {
//query 1
List<CarP> cars=carRepo.findCarProjections(carIds);
//query 2
List<SomeotherEntity> cars=otherRepo.findSomethingElse(params);
//even query 1 and query2 is not executing in a single JDBC connection
//Do Something
}

}
我想提高性能,欢迎任何建议


有没有办法避免JDBC查询准备时间或JDBC连接获取时间?

非常令人惊讶的是,在我当前的应用程序后期部署中也遇到了类似的性能问题。幸运的是,我们能够修复它

根本原因:我们发现在@Query中使用多个输入参数会导致性能问题

@Query(SELECT u.carName as carName, u.carId as carId from Car u where u.carId in (:carIds))

解决方案:改为使用entityManager动态生成类似查询,并观察到显著的性能改进

如何使用entityManager启用会话度量?使用Entity Manager打印了以下指标,即“认为是正确的”。由于执行时间显示为0,您所说的会话度量是什么意思?您是否尝试过entityManager并发现性能有所提高?