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 在一些情况下自动禁用批量功能,需要手动启用。
本文参考链接:https://blog.csdn.net/neweastsun/article/details/103783191