一、jpa批量新增数据
saveAll()方法不可取,看下源码就知道其原理是 for 循环每一条数据,然后先select一次,如果数据库存在,则update。如果不存在,则insert。
相关源码如下:
@Transactional
public <S extends T> List<S> saveAll(Iterable<S> entities) {
Assert.notNull(entities, "Entities must not be null!");
List<S> result = new ArrayList<S>();
for (S entity : entities) {
result.add(save(entity));
}
return result;
}
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
解决方法:只基于jpa作优化,jdbc、mybatis不在讨论范围之内(原生SQL大法好)
@PersistenceContext
private EntityManager entityManager;
@Override
@Transactional
public void addBatch(List<ProjectApplyDO> list) {
for (ProjectApplyDO projectApplyDO : list) {
entityManager.persist(projectApplyDO);
}
entityManager.flush();
entityManager.clear();
}
二、jpa分页查询
非原生SQL(条件包含字符串、日期类型)例子如下:
public Page<ProjectApplyDO> findAll(ProjectApplyDO projectApplyDO, PageDO pageDO) {
Sort sort = new Sort(Sort.Direction.DESC, "id");
// 分页从0开始
Pageable pageable = PageRequest.of(pageDO.getCurrent() - 1, pageDO.getSize(), sort);
return projectApplyDao.findAll((Specification<ProjectApplyDO>) (root, query, builder) -> {
Predicate predicate = builder.conjunction();
List<Expression<Boolean>> list = predicate.getExpressions();
if (projectApplyDO.getUuid() != null) {
list.add(builder.equal(root.get("uuid"), projectApplyDO.getUuid()));
}
if (projectApplyDO.getProjectName() != null) {
list.add(builder.like(root.get("projectName"), "%" + projectApplyDO.getProjectName() + "%"));
}
if (projectApplyDO.getApplyStartDate() != null) {
list.add(builder.greaterThan(root.get("applyStartDate"), projectApplyDO.getApplyStartDate()));
}
if (projectApplyDO.getApplyEndDate() != null) {
list.add(builder.lessThan(root.get("applyEndDate"), projectApplyDO.getApplyEndDate()));
}
return predicate;
}, pageable);
}
三、原生SQL增删改查
- 使用 EntityManager 实现增删改查,应该是学习成本最低的一种方式。
@PersistenceContext
private EntityManager entityManager;
public List<ProjectApplyDO> findAll(ProjectApplyDO projectApplyDO, PageDO pageDO) {
// 字符串任意拼接
String sql = ...
Query sql = entityManager.createNativeQuery(sql, ProjectApplyDO.class);
return sql.getResultList();
}
- 使用注解 @Query
2.1、参数为 Entity 对象,语法比较古怪
@Modifying
@Query(value = "insert into cms_system_notice (content, start_date, end_date, create_user) values (:#{#notice.content}, :#{#notice.startDate}, :#{#notice.endDate}, :#{#notice.createUser})", nativeQuery = true)
void insert(@Param("notice") SystemNoticeDO systemNoticeDO);
2.2、参数为基本类型
@Modifying
@Query(value = "update cms_system_notice set status = :status where id = :id", nativeQuery = true)
void updateStatus(@Param("id") int id, @Param("status") int status);
用mybatis,基于注解开发,也没什么配置,只需要会原生SQL,就可以上手了。
相比之下,jpa麻烦多了,还涉及一些SQL优化,控制台打印SQL因为表名别名原因,也不简洁美观。