JPA使用中应注意的地方
JPA使用中应注意的地方
写在前面
一、事务处理
@Transactional,这个注解,想要关联事务处理,要特别注意异常处理
二、保存和批量保存
关于JPA中save,saveAndFlush和saveAll的区别,
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
@Transactional
public <S extends T> S saveAndFlush(S entity) {
S result = save(entity);
flush();
return result;
}
@Transactional
public <S extends T> List<S> saveAll(Iterable<S> entities) {
Assert.notNull(entities, "The given Iterable of entities not be null!");
List<S> result = new ArrayList<S>();
for (S entity : entities) {
result.add(save(entity));
}
return result;
}
注意这里不只是源码这么简单,下面我写了测试代码,可以看出,saveAll不只是 For 遍历这么简单,可能是在批量保存的时候,之建立一次连接
// 测试,耗时约 130-170 s
@GetMapping("/batch-add")
public ResultBean batchAdd() {
LocalDateTime start = LocalDateTime.now();
for (int i = 60000; i < 61000; i++) {
UserInfo u = new UserInfo();
u.setUserName("name" + i);
u.setUserCode("code" + i);
userRepository.save(u);
}
LocalDateTime end = LocalDateTime.now();
return ResultBean.ok(ChronoUnit.SECONDS.between(start,end));
}
// 测试,耗时约 1 s
@GetMapping("/batch-all")
public ResultBean batchAllAdd() {
ArrayList<UserInfo> list = Lists.newArrayList();
LocalDateTime start = LocalDateTime.now();
for (int i = 61000; i < 62000; i++) {
UserInfo u = new UserInfo();
u.setUserName("name" + i);
u.setUserCode("code" + i);
list.add(u);
}
userRepository.saveAll(list);
LocalDateTime end = LocalDateTime.now();
return ResultBean.ok(ChronoUnit.SECONDS.between(start, end));
}
三、SQL日志打印问题
SQl日志打印是有问题的,不要太纠结这个问题,比如SQL怎么顺序不对?多测试,检查数据