实现场景
最近在写一个有关拼团旅游的业务,里面有这样一个逻辑实现:一个拼团活动表Activity对应多个Travel旅游表,travel旅游表要分段存储前端传来的List<TravelSchedulingVO>,Travel表需将每一条数据保存入库,这时候就需要用到批量插入来实现了,由于项目的orm框架使用的是Spring Data JPA,所有我们来讨论一下JPA的批量插入的实现和原理。
Spring Data JPA中保存方法已经帮我们封装好了,有save(),saveAll(),而saveAll()是用来实现数据的批量插入的,我们先看看save和savaAll()这两个方法的源码:
save()
saveAll()
从源码可以看到,saveAll()批量插入就是循环调用save()方法啊,我们来写个简单的测试插入数据方法试一下:
项目信息:
UserController
@Controller
public class UserController {
@Autowired
UserRepository userRepository;
@PostMapping("/saveall")
@ResponseBody
public String saveAll() {
long start = System.currentTimeMillis();
List<User> list = new ArrayList<>();
for (int i = 10000; i < 10005; i++) {
User user = new User();
user.setUsername("这是用户名测试数据" + i);
list.add(user);
}
userRepository.saveAll(list);
long end = System.currentTimeMillis();
long time = end - start;
System.out.println(LocalDateTime.now() + " 共用时 " + time);
return "success";
}
}
DruidConfiguration
/**
* @Author 林必昭
* @Date 2019/11/21 11:10
*/
@Configuration
@PropertySource(value = "application.properties")
public class DruidConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druidDataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
return druidDataSource;
}
/**
* 注册一个StatViewServlet
* @return
*/
@Bean
public ServletRegistrationBean druidStatViewServlet(){
//org.springframework.boot.context.embedded.ServletRegistrationBean提供类的进行注册.
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*");
//添加初始化参数:initParams
//白名单:
servletRegistrationBean.addInitParameter("allow","127.0.0.1");
//IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的话提示:Sorry, you are not permitted to view this page.
servletRegistrationBean.addInitParameter("deny","192.168.1.73");
//登录查看信息的账号密码.
servletRegistrationBean.addInitParameter("loginUsername","root");
servletRegistrationBean.addInitParameter("loginPassword","admin");
//是否能够重置数据.
servletRegistrationBean.addInitParameter("resetEnable","false");
return servletRegistrationBean;
}
/**
* 注册一个:filterRegistrationBean
* @return
*/
@Bean
public FilterRegistrationBean druidStatFilter(){
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
//添加过滤规则.
filterRegistrationBean.addUrlPatterns("/*");
//添加不需要忽略的格式信息.
filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
return filterRegistrationBean;
}
}
运行Appliaction,使用IDEA Http Client测试一下saveAll方法,配置打开了Hibernate显示sql日志,看一下输出结果::
看日志,JPA是先把所有的数据全查出来了,如果数据库有就更新,没有就新增。我们访问 http://localhost:8080/druid/login.html 输入账户名root,密码admin登录,看一下阿里Druid的SQL监控:
可以看到我们插入了5条数据,执行了7次sql操作,因为我们spring.jpa.hibernate.ddl-auto=create-drop,JPA会帮我们自动创建和删除库,好像没有什么问题。。。