Spring Data JPA 实现批量插入

Spring Data JPA 实现批量插入

数据库操作是非常昂贵的,我们可以通过采用批量操作提升性能并维护一致性。本文通过示例说明Spring Data JPA的批量操作。

1. 环境准备

1.1. 依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
   <version>2.1.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.197</version>
</dependency>

你可以选择最新版本,这里为了方便采用h2数据库。

1.2. 实体类

这里简单定义实体类Customer:

Entity
public class Customer {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String firstName;
    private String lastName;
 
    // constructor, getters, setters 
}

1.2. 定义Repository

接着定义Repository:

public interface CustomerRepository extends CrudRepository<Customer, Long> {
}

下面利用saveAll方式实现批量插入。

1.3. 定义Controller

在Controller中注入customerRepository,调用saveAll方法实现批量插入:

@RestController
public class CustomerController {   
    @Autowired
    CustomerRepository customerRepository;   
 
    @PostMapping("/customers")
    public ResponseEntity<String> insertCustomers() {        
        Customer c1 = new Customer("James", "Gosling");
        Customer c2 = new Customer("Doug", "Lea");
        Customer c3 = new Customer("Martin", "Fowler");
        Customer c4 = new Customer("Brian", "Goetz");
        List<Customer> customers = Arrays.asList(c1, c2, c3, c4);
        customerRepository.saveAll(customers);
        return ResponseEntity.created("/customers");
    }
 
    // ... @GetMapping to read customers
}

1.4. 测试验证

@Autowired
private MockMvc mockMvc;
 
@Test
public void whenInsertingCustomers_thenCustomersAreCreated() throws Exception {
    this.mockMvc.perform(post("/customers"))
      .andExpect(status().isCreated()));
}

这样就完成了批量插入操作,真的能起作用吗?下面我们配置日志进行验证。

2. 验证批量操作

为了验证,我们在application.properties文件中增加下面属性看一些统计信息:

spring.jpa.properties.hibernate.generate_statistics=true

这是运行测试程序,看下面统计数据:

11232586 nanoseconds spent preparing 4 JDBC statements;
4076610 nanoseconds spent executing 4 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;

从上面信息可以看到,确实创建了4个customer,但在批操作中没有它们。原因是在有些情况下批量操作默认没有启用,我们示例中id是自动生成的,这时saveAll缺省不采用批量操作。现在我们启用批量操作相关配置:

spring.jpa.properties.hibernate.jdbc.batch_size=4
spring.jpa.properties.hibernate.order_inserts=true

第一个属性告诉Hibernate收集插入批为4。 order_insert属性告诉Hibernate花时间按实体对插入进行分组,从而创建更大的批。

接着第二次运行测试,输出日志为:

16577314 nanoseconds spent preparing 4 JDBC statements;
2207548 nanoseconds spent executing 4 JDBC statements;
2003005 nanoseconds spent executing 1 JDBC batches;

对于更新和删除也可以使用相同的方法,Hibernate也提供了order_updates属性。

3. 总结

使用批量插入可以提升性能。Spring Data Jpa 在一些情况下自动禁用批量功能,需要手动启用。

发布了395 篇原创文章 · 获赞 761 · 访问量 143万+

猜你喜欢

转载自blog.csdn.net/neweastsun/article/details/103783191