spring batch 中JpaNamedQueryProvider、JpaNativeQueryProvider两种查询方式对比

完整代码示例:对比两种查询方式

// Employee.java 实体类(包含命名查询)
@Entity
@NamedQuery(name = "Employee.findAllNamedQuery", 
            query = "SELECT e FROM Employee e ORDER BY e.id") // 定义命名查询
public class Employee {
    @Id
    private Long id;
    private String name;
    private Double salary;
    // getters/setters
}

// JobConfig.java 配置类
@Configuration
@EnableBatchProcessing
public class JobConfig {

    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @Bean
    public Job employeeJob() {
        return jobBuilderFactory.get("employeeJob")
                .start(employeeStep1()) // 使用命名查询的步骤
                .next(employeeStep2())  // 使用原生查询的步骤
                .build();
    }

    // 使用JpaNamedQueryProvider的步骤
    @Bean
    public Step employeeStep1(JpaPagingItemReader<Employee> namedQueryReader) {
        return stepBuilderFactory.get("step1")
                .<Employee, Employee>chunk(10)
                .reader(namedQueryReader)
                .writer(items -> items.forEach(System.out::println))
                .build();
    }

    // 使用JpaNativeQueryProvider的步骤
    @Bean
    public Step employeeStep2(JpaPagingItemReader<Employee> nativeQueryReader) {
        return stepBuilderFactory.get("step2")
                .<Employee, Employee>chunk(10)
                .reader(nativeQueryReader)
                .writer(items -> items.forEach(System.out::println))
                .build();
    }

    // 命名查询配置
    @Bean
    public JpaPagingItemReader<Employee> namedQueryReader() {
        return new JpaPagingItemReaderBuilder<Employee>()
            .name("namedQueryReader")
            .entityManagerFactory(entityManagerFactory)
            .pageSize(50)
            .queryProvider(new JpaNamedQueryProvider("Employee.findAllNamedQuery"))
            .build();
    }

    // 原生查询配置
    @Bean
    public JpaPagingItemReader<Employee> nativeQueryReader() {
        return new JpaPagingItemReaderBuilder<Employee>()
            .name("nativeQueryReader")
            .entityManagerFactory(entityManagerFactory)
            .pageSize(50)
            .queryProvider(new JpaNativeQueryProvider<>(
                "SELECT e.id, e.name, e.salary FROM EMPLOYEE e ORDER BY e.id", // 原生SQL
                Employee.class, // 映射实体
                new String[]{"id", "name", "salary"} // 列名到属性的映射
            ))
            .build();
    }
}

// SpringBatchApplication.java 启动类
@SpringBootApplication
@EnableBatchProcessing
public class SpringBatchApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBatchApplication.class, args);
    }
}

关键代码说明:

  1. JpaNamedQueryProvider

    • 通过实体类上的@NamedQuery定义查询名称和JPQL语句
    • 配置时直接传入命名查询名称
    • 优势:符合JPA规范,编译时检查查询语法
  2. JpaNativeQueryProvider

    • 处理原生SQL查询,需手动指定:
      • SQL语句(注意表名与数据库实际表名一致)
      • 目标实体类型
      • 列名与实体属性的映射关系
    • 适用场景:需要复杂SQL优化或使用数据库特定语法
  3. JpaPagingItemReader

    • 核心分页读取器,自动处理分页逻辑:
      • 使用entityManagerFactory连接数据库
      • 通过pageSize控制每批数据量
      • 支持事务管理(由Spring Batch自动处理)
  4. JpaPagingItemReaderBuilder

    • 通过链式调用简化配置:

      new JpaPagingItemReaderBuilder<>()
          .name("readerName") 
          .entityManagerFactory(...) 
          .pageSize(50) 
          .queryProvider(...) 
          .build();
      
    • 必须配置:entityManagerFactoryqueryProviderpageSize


功能对比表格

类名称 功能描述 使用场景 关键配置参数 注意事项
JpaNamedQueryProvider 基于实体类的命名查询管理 需要复用JPQL查询 查询名称(String) 需与实体类的@NamedQuery一致
JpaNativeQueryProvider 管理原生SQL查询,支持列名到实体属性的映射 需要执行原生SQL查询 SQL语句、实体类型、属性列名映射数组 需确保列名与实体属性严格对应
JpaPagingItemReader 分页读取数据的核心组件,支持数据库连接和分页逻辑 所有需要分页读取数据的场景 entityManagerFactory、pageSize、查询提供者 需配合Spring Batch事务管理
JpaPagingItemReaderBuilder 构建JpaPagingItemReader的辅助类,提供链式配置方式 需要简化配置流程 name、entityManagerFactory、pageSize、查询提供者 所有参数必须显式配置

使用要点总结:

  1. 命名查询:需在实体类上通过@NamedQuery定义,保证查询名称一致性
  2. 原生查询
    • 表名需与数据库实际表名一致(区分大小写)
    • 列名必须与实体属性严格对应(如:id对应Employee.id
  3. 分页性能
    • pageSize需根据数据库性能调整,建议50-1000之间
    • 分页使用OFFSET时需注意数据库性能(如MySQL InnoDB的优化)
  4. 事务管理:Spring Batch会自动管理事务,但需确保EntityManagerFactory配置正确
  5. 数据映射:原生查询需手动指定列名映射,命名查询自动通过实体属性映射

你可能感兴趣的:(Java,基础整理,spring,batch,oracle)