美文网首页
jpa操作数据库问题总结

jpa操作数据库问题总结

作者: 纳米君 | 来源:发表于2020-06-09 15:31 被阅读0次

    一、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增删改查

    1. 使用 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();
        }
    
    1. 使用注解 @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因为表名别名原因,也不简洁美观。

    相关文章

      网友评论

          本文标题:jpa操作数据库问题总结

          本文链接:https://www.haomeiwen.com/subject/ocwstktx.html