zoukankan      html  css  js  c++  java
  • SpringBoot与Jpa自定义增删查改

    一、引入依赖

    <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    二、简单的增删查改

    model实体类

    @Entity
    @NoArgsConstructor
    @Data
    public class ProductLoadRecord implements Serializable {
        private static final long serialVersionUID = 7676163793637224150L;
        @Id
        private Long id;
    
        private Long batchId;
    
        private String code;
    
        private String name;
    
        private String content;
    
        private String status;
        @Column(name = "datatime", columnDefinition = "DATETIME")
        private Date datatime;
        
    }

    以上的@Entity、@Table、@Column注解的用法可以查阅网址:

    https://www.cnblogs.com/softidea/p/6216722.html

    dao层

    一般简单的增删查改,只需要实现JpaRepository。如果没有提供的方法,可以使用 @Query注解来进行增删查改。

    public interface OrderRepository extends JpaRepository<OrderInfo,String> {
        @Query(value="SELECT * from order_info where lock_user_id=?1 AND status=1",nativeQuery=true)
        List<OrderInfo> selectMyOrders(String lockUserId);
    
        @Modifying
        @Transactional
        @Query(value="UPDATE order_info SET lock_user_id = NULL AND status = 0 WHERE order_id = ?1",nativeQuery = true)
        void unlockOrderByOrderId(String orderId);
    }

    service层

    增删改不难,简单的实例对象分页查询

    public Map select(Integer pageNum,Integer pageSize,Province province){
            Page<Province> provinces = provinceRepository.findAll(Example.of(province), PageRequest.of(pageNum - 1, pageSize));
        }

    三、复杂的多条件分页查询

    model实体类

    订单实体类,与商品实体类是一对多的关系

    @Data
    @Entity
    @NoArgsConstructor
    public class OrderInfo implements Serializable {
        private static final long serialVersionUID = 1063821955023696541L;
    
        @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
        @JoinColumn(name = "orderId")
        private List<GoodsInfo> goodsInfos;
    }

    dao层

    复杂的多条件查询需要实现JpaSpecificationExecutor。

    public interface OrderRepository extends JpaRepository<OrderInfo,String>, JpaSpecificationExecutor<OrderInfo> {
      
    }

    service层

    重写specification。下面的代码实现了多条件的两表联查分页查询。

    通过条件构造中把各种条件拼接在一起,合并成总条件specification。

    public Page<OrderInfo> getOrders(OrderPageQuery orderPageQuery){
            Specification<OrderInfo> specification = new Specification<OrderInfo>() {
                @Override
                public Predicate toPredicate(Root<OrderInfo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    // 建立子查询
                    Subquery<GoodsInfo> goodsSubquery = query.subquery(GoodsInfo.class);
                    Root<GoodsInfo> goodsInfoRoot = goodsSubquery.from(GoodsInfo.class);
                    goodsSubquery.select(goodsInfoRoot.get("goodsSku"));
    ​
                    List<Predicate> orderInfo = new ArrayList<Predicate>();
                    List<Predicate> goodsInfo = new ArrayList<Predicate>();
                    Date createStartDate = orderPageQuery.getCreateStartDate();
                    Date createEndDate = orderPageQuery.getCreateEndDate();
                    String custName = orderPageQuery.getCustName();
                    String goodsName = orderPageQuery.getGoodsName();
                    String custType = orderPageQuery.getCustType();
                    Integer status = orderPageQuery.getStatus();
                    if (createStartDate != null && createEndDate != null) {
                        orderInfo.add(cb.between(root.get("createDt"),createStartDate,createEndDate));
                    }
                    if(custName != null){
                        orderInfo.add(cb.like(root.get("custName"),"%"+custName+"%"));
                    }
                    if(goodsName != null){
                        goodsInfo.add(cb.like(goodsInfoRoot.get("goodsName"),"%"+goodsName+"%"));
                    }
                    if(custType != null){
                        orderInfo.add(cb.equal(root.get("custType").as(String.class),custType));
                    }
                    if(status != null){
                        orderInfo.add(cb.equal(root.get("status").as(Integer.class),status));
                    }
                    if(goodsInfo.size() > 0){
                        // 子查询与父查询相关联
                        goodsInfo.add(cb.equal(goodsInfoRoot.get("orderId"),root.get("orderId")));
                        // 拼接过滤条件
                        goodsSubquery.where(goodsInfo.toArray(new Predicate[goodsInfo.size()]));
                        // 和总条件拼接(exists的使用)
                        orderInfo.add(cb.exists(goodsSubquery));
                    }
                    return query.where(orderInfo.toArray(new Predicate[orderInfo.size()])).getRestriction();
                }
            };
            Page<OrderInfo> orders = orderRepository.findAll(specification, PageRequest.of(orderPageQuery.getPage() - 1, orderPageQuery.getPageSize()));
            return orders;
        }

    可以参考下面的网址,一个复杂的查询例子(包含常用的所有查询方法):

    https://www.cnblogs.com/g-smile/p/9177841.html

    注意:但是这种实现JpaSpecificationExecutor,重写specification的方法,不能单独对表字段查询,例如:

    select id,code from order.......,只能相当于select *这样。

    四、复杂的多条件分页查询(另一种方法)

    实现方式

    EntityManager:EntityManager是JPA中用于增删改查的接口,它的作用相当于一座桥梁,连接内存中的java对象和数据库的数据存储。可以用getCriteriaBuilder()的方式获取CriteriaBuilder对象。

    CriteriaBuilder接口:用于构造标准查询、复合条件、表达式、排序等。可以通过createQuery的方式获取CriteriaQuery实例。

    CriteriaQuery接口:代表一个specific的顶层查询对象,它包含着查询的各个部分,比如:select 、from、where、group by、order by。

    Root接口:代表Criteria查询的根对象,定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似 。

    实现代码

      //通过注解@PersistenceContext注入的方式来获得EntityManager对象
        @PersistenceContext
        private EntityManager entityManager;
     
        public void multiQueryStudent (StudentParam studentParam) {   //studentParam:自定义的查询参数体
            List<String> schoolList = studentParam.getSchoolList();   //查询条件:学校List
            String startDate = studentParam.getStartDate();   //查询条件:出生日期-起
            String endDate = studentParam.getEndDate();   //查询条件:出生日期-止
            CriteriaBuilder cb = entityManager.getCriteriaBuilder();
            //StudentScoreSum指定了查询结果返回至自定义对象
            CriteriaQuery<StudentScoreSum> query = cb.createQuery(StudentScoreSum.class);
            Root<StudentEntity> root = query.from(StudentEntity.class);
            Path<String> schoolPath = root.get("school");
            Path<Integer> scorePath = root.get("score");
            Path<String> namePath = root.get("name");
            Path<String> birthdayPath = root.get("birthday");
            //拼接where条件
            List<Predicate> predicateList = new ArrayList<Predicate>();
            if (schoolList != null && schoolList.size() > 0) {
                CriteriaBuilder.In<String> in = cb.in(schoolPath);
                for (String school : schoolList) {
                    in.value(school);
                }
                predicateList.add(in);
            }
            if (startDate != null && !"".equals(startDate)) {
                predicateList.add(cb.greaterThan(birthdayPath, startDate));
            }
            if (endDate != null && !"".equals(endDate)) {
                predicateList.add(cb.lessThan(birthdayPath, endDate));
            }
            Predicate[] predicates = new Predicate[predicateList.size()];
            predicates = predicateList.toArray(predicates);
            //加上where条件
            query.where(predicates);
            //指定查询项,select后面的东西
            query.multiselect(schoolPath, cb.count(root).as(Integer.class), cb.sum(scorePath), namePath, cb.max(scorePath));
            //按学校分组
            query.groupBy(schoolPath);
            //排序
            query.orderBy(cb.desc(cb.max(scorePath)));
            //筛选第一名成绩大于80分的
            query.having(cb.greaterThan(cb.max(scorePath), 80));
            TypedQuery<StudentScoreSum> q = entityManager.createQuery(query);
            List<StudentScoreSum> result = q.getResultList();
            for (StudentScoreSum studentScoreSum : result) {
                //打印查询结果
                System.out.println(studentScoreSum.toString());
            }
        }

    具体可以参考下面的网址:

    https://blog.csdn.net/liuyunyihao/article/details/81255731

    注意:这种实现方式不能返回分页Page给前端,会把所有的数据查询出来,效率慢。

  • 相关阅读:
    Spring的声明试事务
    spring-AOP-添加日志
    弹窗插件
    工厂设计模式
    smartUpload组件批量下载
    简单的C++委托 —— 用模板类实现类成员函数的回调
    偷Microsoft师学MFC艺:且看C++如何支持反射
    C++中回调(CallBack)的使用方法
    epoll 使用实例
    C++成员函数指针的应用
  • 原文地址:https://www.cnblogs.com/slivelove/p/9877123.html
Copyright © 2011-2022 走看看