美文网首页
Spring data jpa 使用

Spring data jpa 使用

作者: Pts | 来源:发表于2019-01-11 10:46 被阅读0次

    spring data jpa介绍

    首先了解JPA是什么?
    JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据。他的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结束现在Hibernate,TopLink,JDO等ORM框架各自为营的局面。值得注意的是,JPA是在充分吸收了现有Hibernate,TopLink,JDO等ORM框架的基础上发展而来的,具有易于使用,伸缩性强等优点。从目前的开发社区的反应上看,JPA受到了极大的支持和赞扬,其中就包括了Spring与EJB3.0的开发团队。
    注意:JPA是一套规范,不是一套产品,那么像Hibernate,TopLink,JDO他们是一套产品,如果说这些产品实现了这个JPA规范,那么我们就可以叫他们为JPA的实现产品。

    spring data jpa

    Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率!

    添加spring-data-jpa的支持

    <!--引入JPA的依赖关系-->
    <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    

    spring data jpa让我们解脱了DAO层的操作,基本上所有CRUD(增删改查)都可以依赖于它来实现

    编写实体类
    package com.mengma.tensquare_base.pojo;
    
    
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    @Entity
    @Table(name = "tb_label") //name = 表名
    public class Label {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id", updatable = false) // 与表字段一致 则可以不加
        private String id;
    
        private String labelname;
    
        private String state;
    
        private Long count;
    
        private String recommend;
    
        private Long fans;
    
        public Label(String id, String labelname, String state, Long count, String recommend, Long fans) {
            this.id = id;
            this.labelname = labelname;
            this.state = state;
            this.count = count;
            this.recommend = recommend;
            this.fans = fans;
        }
    
        public Label() {
            super();
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id == null ? null : id.trim();
        }
    
        public String getLabelname() {
            return labelname;
        }
    
        public void setLabelname(String labelname) {
            this.labelname = labelname == null ? null : labelname.trim();
        }
    
        public String getState() {
            return state;
        }
    
        public void setState(String state) {
            this.state = state == null ? null : state.trim();
        }
    
        public Long getCount() {
            return count;
        }
    
        public void setCount(Long count) {
            this.count = count;
        }
    
        public String getRecommend() {
            return recommend;
        }
    
        public void setRecommend(String recommend) {
            this.recommend = recommend == null ? null : recommend.trim();
        }
    
        public Long getFans() {
            return fans;
        }
    
        public void setFans(Long fans) {
            this.fans = fans;
        }
    }
    
    编写Repository接口
    //此接口不需要添加注解
    //当需要条件查询时,需要继承JpaSpecificationExecutor 
    public interface LabelDao extends JpaRepository<Label,String>,JpaSpecificationExecutor<Label> {
           List<Label> findAllByRecommend(String recommend);
           List<Label> findAllByState(String state);
    }
    
    编写实现层
    package com.mengma.tensquare_base.service;
    
    import com.mengma.common.utils.UUIDUtil;
    import com.mengma.tensquare_base.dao.LabelDao;
    import com.mengma.tensquare_base.pojo.Label;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.jpa.domain.Specification;
    import org.springframework.stereotype.Service;
    
    import javax.persistence.criteria.CriteriaBuilder;
    import javax.persistence.criteria.CriteriaQuery;
    import javax.persistence.criteria.Predicate;
    import javax.persistence.criteria.Root;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Optional;
    
    /**
     * @author Administrator
     * @Title: LabelRepositoryService
     * @ProjectName tensquare_abu
     * @Description: TODO
     * @date 2019/1/11 0:32
     */
    @Service
    public class LabelRepositoryService {
        @Autowired
        private LabelDao labelDao;
        public Label insert(Label label){
            String id = UUIDUtil.getOrderIdByUUId();
            label.setId(id);
    //     新增
            return  labelDao.save(label);
        }
        public List<Label> getList(){
    //     查询所有
            return labelDao.findAll();
        }
        public List<Label> findByRecommend(String recommend){
    //    根据条件查询
            return labelDao.findAllByRecommend(recommend);
        }
        public List<Label> findByState(String state){
            return labelDao.findAllByState(state);
        }
        public Label findById(String labelId){
    //    根据id 查询
            return  labelDao.findById(labelId).get();
        }
        public Label update(Label label){
    //    修改  save 即可做新增 也可做修改  是根据id进行判断 如果通过id查询数据库没有数据 则进行新增 反之
            return  labelDao.save(label);
        }
        public void delete(String labelId){
    //  删除
            labelDao.deleteById(labelId);
        }
        public List<Label> pageSearch(Label label){
    //  不带条件的分页
            return labelDao.findAll(new Specification<Label>() {
                //root: 根对象 也就是要把条件封装到那个对象
                //query: 封装的是查询的关键字  比如 group by ,order by 等
                //criteriaBuilder: 用来封装条件对象 如果直接返回null 表示不需要任何条件
                @Override
                public Predicate toPredicate(Root<Label> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                    List<Predicate> list = new ArrayList<>();
                    if (!StringUtils.isBlank(label.getLabelname())) {
                        Predicate labelname = criteriaBuilder.like(root.get("labelname").as(String.class), "%" + label.getLabelname() + "%");
                        list.add(labelname);
                    }
                    if (!StringUtils.isBlank(label.getState())) {
                        Predicate state = criteriaBuilder.equal(root.get("state").as(String.class), label.getState());
                        list.add(state);
                    }
                    if (!StringUtils.isBlank(label.getRecommend())) {
                        Predicate recommend = criteriaBuilder.equal(root.get("recommend").as(String.class), label.getRecommend());
                        list.add(recommend);
                    }
                    //criteriaBuilder.and(predicates数组) 由于predicates的数组长度未定 因此上面先定义用集合接收  然后在转为数组
                    Predicate[] predicates = new Predicate[list.size()];
                    predicates = list.toArray(predicates);
                    return criteriaBuilder.and(predicates);//相当于 where loginname like '%java%' and state="1"
                }
            });
        }
    
        public Page<Label> page(Integer page, Integer size, Label label){
            Pageable pageable = PageRequest.of(page-1,size);
    //  带条件的分页查询
           return labelDao.findAll(new Specification<Label>() {
               //root: 根对象 也就是要把条件封装到那个对象
               //query: 封装的是查询的关键字  比如 group by ,order by 等
               //criteriaBuilder: 用来封装条件对象 如果直接返回null 表示不需要任何条件
               @Override
               public Predicate toPredicate(Root<Label> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                   List<Predicate> list = new ArrayList<>();
                   if (!StringUtils.isBlank(label.getLabelname())) {
                       Predicate labelname = criteriaBuilder.like(root.get("labelname").as(String.class), "%" + label.getLabelname() + "%");
                       list.add(labelname);
                   }
                   if (!StringUtils.isBlank(label.getState())) {
                       Predicate state = criteriaBuilder.equal(root.get("state").as(String.class), label.getState());
                       list.add(state);
                   }
                   if (!StringUtils.isBlank(label.getRecommend())) {
                       Predicate recommend = criteriaBuilder.equal(root.get("recommend").as(String.class), label.getRecommend());
                       list.add(recommend);
                   }
                   //criteriaBuilder.and(predicates数组) 由于predicates的数组长度未定 因此上面先定义用集合接收  然后在转为数组
                   Predicate[] predicates = new Predicate[list.size()];
                   predicates = list.toArray(predicates);
                   return criteriaBuilder.and(predicates);//相当于 where loginname like '%java%' and state="1"
               }
           },pageable);
        }
    }
    
    
    package com.mengma.tensquare_base.controller;
    
    import com.mengma.common.VO.PageResult;
    import com.mengma.common.commons.ServerResponse;
    import com.mengma.tensquare_base.dao.LabelDao;
    import com.mengma.tensquare_base.pojo.Label;
    import com.mengma.tensquare_base.service.LabelRepositoryService;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.jpa.domain.Specification;
    import org.springframework.web.bind.annotation.*;
    
    import javax.persistence.criteria.CriteriaBuilder;
    import javax.persistence.criteria.CriteriaQuery;
    import javax.persistence.criteria.Predicate;
    import javax.persistence.criteria.Root;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author Administrator
     * @Title: LabelController
     * @ProjectName tensquare_abu
     * @Description: TODO
     * @date 2019/1/10 15:17
     */
    @RestController
    @RequestMapping("/")
    public class LabelController {
        @Autowired
        private LabelRepositoryService labelRepositoryService;
        /**
        * @Description: 增加标签
        * @Param:  
        * @return:  
        * @Author: ABU
        * @Date: 2019/1/10 
        */
        @PostMapping("label")
        public ServerResponse insert(@RequestBody Label label){
            Label insert = labelRepositoryService.insert(label);
            if(insert==null){
                return ServerResponse.createByErrorMessage("添加失败");
            }
            return ServerResponse.createByflagMessage("添加成功");
        }
        @GetMapping("label")
        public ServerResponse getLists(){
            return  ServerResponse.createByflag(labelRepositoryService.getList());
        }
        @GetMapping("label/toplist")
        public ServerResponse topLists(){
            return ServerResponse.createByflag(labelRepositoryService.findByRecommend("1"));
        }
        @GetMapping("label/list")
        public ServerResponse stateLists(){
            return ServerResponse.createByflag(labelRepositoryService.findByState("1"));
        }
        @GetMapping("label/{labelId}")
        public ServerResponse getById(@PathVariable String labelId){
            return ServerResponse.createByflag(labelRepositoryService.findById(labelId));
        }
        @PutMapping("/label/{labelId}")
        public ServerResponse update(@PathVariable String labelId,
                                     @RequestBody Label label){
            //sava 既可以做保存 又可以做修改 根据传入的类的id 进行查询,没有就新增 反之
            label.setId(labelId);
            Label save = labelRepositoryService.update(label);
            if (save==null){
                return ServerResponse.createByErrorMessage("失败");
            }
            return ServerResponse.createByflagMessage("成功!");
        }
        @DeleteMapping("label/{labelId}")
        public ServerResponse delete(@PathVariable String labelId){
            labelRepositoryService.delete(labelId);
           return ServerResponse.createByflagMessage("成功!");
        }
    
        @PostMapping("label/search")
        public ServerResponse pageSearch(@RequestBody Label label){
            return ServerResponse.createByflag(labelRepositoryService.pageSearch(label));
        }
        @PostMapping("label/search/{page}/{size}")
        public ServerResponse page(@PathVariable Integer page,
                                   @PathVariable Integer size,
                                   @RequestBody  Label label){
            Page<Label> page1 = labelRepositoryService.page(page, size, label);
            PageResult pageResult = new PageResult();
            pageResult.setTotal(page1.getTotalElements());
            pageResult.setRows(page1.getContent());
            return ServerResponse.createByflag(pageResult);
        }
    
    }
    

    在此处介绍一下上面提到的自定义Repository继承的两个接口,如果你的查询列表是没有查询条件,只是列表展示和分页,只需继承JpaRepository接口即可,但是如果你的查询列表是带有多个查询条件的话则需要继承JpaSpecificationExecutor接口,这个接口里面定义的多条件查询的方法。当然不管继承哪个接口,当你做分页查询时,都是需要调用findAll方法的,这个方法是jap定义好的分页查询方法。

    下面介绍一下一些简单的默认查询

    自定义简单查询

    自定义的简单查询就是根据方法名来自动生成SQL,主要的语法是
    findXXBy,readAXXBy,queryXXBy,countXXBy, getXXBy后面跟属性名称:

    也使用一些加一些关键字 And、 Or

    User findByUserNameOrEmail(String username, String email);
    

    修改、删除、统计也是类似语法

    Long deleteById(Long id);
    
    Long countByUserName(String userName)
    

    基本上SQL体系中的关键词都可以使用,例如:LIKE、 OrderBy。

    List<User> findByEmailLike(String email);
        
    List<User> findByUserNameOrderByEmailDesc(String email);
    

    具体的关键字,使用方法和生产成SQL如下表所示

    image.png
    image.png
    复杂查询

    在实际的开发中我们需要用到分页、删选、连表等查询的时候就需要特殊的方法或者自定义SQL
    分页查询
    分页查询在实际使用中非常普遍了,spring data jpa 已经帮我们实现了分页的功能,在查询的方法中,需要传入参数Pageable
    ,当查询中有多个参数的时候 Pageable建议做为最后一个参数传入

    Page<User> findALL(Pageable pageable);
        
    Page<User> findByUserName(String userName,Pageable pageable);
    

    Pageable 是spring封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则

    @Test
    public void testPageQuery() throws Exception {
        int page=1,size=10;
        Sort sort = new Sort(Direction.DESC, "id");
        Pageable pageable = new PageRequest(page, size, sort);
        userRepository.findALL(pageable);
        userRepository.findByUserName("testName", pageable);
    }
    
    限制查询

    有时候我们只需要查询前N个元素,或者支取前一个实体。

    User findFirstByOrderByLastnameAsc();
    
    User findTopByOrderByAgeDesc();
    
    Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
    
    List<User> findFirst10ByLastname(String lastname, Sort sort);
    
    List<User> findTop10ByLastname(String lastname, Pageable pageable);
    
    自定义SQL查询

    其实Spring data 觉大部分的SQL都可以根据方法名定义的方式来实现,但是由于某些原因我们想使用自定义的SQL来查询,spring data也是完美支持的;在SQL的查询方法上面使用 @Query注解,如涉及到删除和修改在需要加上@Modifying.也可以根据需要添加 @Transactional对事物的支持,查询超时的设置等

    @Modifying
    @Query("update User u set u.userName = ?1 where c.id = ?2")
    int modifyByIdAndUserId(String  userName, Long id);
        
    @Transactional
    @Modifying
    @Query("delete from User where id = ?1")
    void deleteByUserId(Long id);
      
    @Transactional(timeout = 10)
    @Query("select u from User u where u.emailAddress = ?1")
        User findByEmailAddress(String emailAddress);
    

    相关文章

      网友评论

          本文标题:Spring data jpa 使用

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