1. 程式人生 > >Spring boot Jpa高階查詢

Spring boot Jpa高階查詢

前言

上一篇文章主要講了Jpa的簡單使用,而在實際專案中並不能滿足我們的需求。如對多張表的關聯查詢,以及查詢時需要的各種條件,這個時候你可以使用自定義SQL語句,但是Jpa並不希望我們這麼做,於是就有了一個擴充套件:使用 Specification 進行查詢

修改相應程式碼

1、修改User.class

程式碼用的上一章的,這裡在User類中進行擴充套件,待會查詢時會用到

@Entity
@Table(name = "user")
public class User {

    //部分程式碼略

    /**
     *  加上該註解,在儲存該實體時,Jpa將為我們自動設定上建立時間
     */
@CreationTimestamp private Timestamp createTime; /** * 加上該註解,在儲存或者修改該實體時,Jpa將為我們自動建立時間或更新日期 */ @UpdateTimestamp private Timestamp updateTime; /** * 關聯角色,測試多表查詢 */ @ManyToOne @JoinColumn(name = "role_id") private Role role; //部分程式碼略 }

2、新增Role.class

@Entity
@Table(name = "role")
public class Role {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true,nullable = false)
    private String name;

	//get set略
}

3、修改UserRepository

要使用Specification,需要繼承JpaSpecificationExecutor介面,修改後的程式碼如下

public interface UserRepo extends JpaRepository<User,Long>, JpaSpecificationExecutor {

}

4、檢視JpaSpecificationExecutor原始碼

Specification是Spring Data JPA提供的一個查詢規範,這裡所有的操作都是圍繞Specification來進行

public interface JpaSpecificationExecutor<T> {
    Optional<T> findOne(@Nullable Specification<T> var1);

    List<T> findAll(@Nullable Specification<T> var1);

    Page<T> findAll(@Nullable Specification<T> var1, Pageable var2);

    List<T> findAll(@Nullable Specification<T> var1, Sort var2);

    long count(@Nullable Specification<T> var1);
}

封裝查詢Service

我這裡簡單做了下簡單封裝,編寫UserQueryService.class

@Service
public class UserQueryService {

    @Autowired
    private UserRepo userRepo;

    /**
     * 分頁加高階查詢
     */
    public Page queryAll(User user, Pageable pageable , String roleName){
        
        return userRepo.findAll(new UserSpec(user,roleName),pageable);
    }

    /**
     * 不分頁
     */
    public List queryAll(User user){
        
        return userRepo.findAll(new UserSpec(user));
    }

    class UserSpec implements Specification<User>{

        private User user;

        private String roleName;

        public UserSpec(User user){
            this.user = user;
        }

        public UserSpec(User user,String roleName){
            this.user = user;
            this.roleName = roleName;
        }

        @Override
        public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {

            List<Predicate> list = new ArrayList<Predicate>();

            /**
             * 左連線,關聯查詢
             */
            Join<Role,User> join = root.join("role",JoinType.LEFT);

            if(!StringUtils.isEmpty(user.getId())){
                /**
                 * 相等
                 */
                list.add(cb.equal(root.get("id").as(Long.class),user.getId()));
            }

            if(!StringUtils.isEmpty(user.getUsername())){
                /**
                 * 模糊
                 */
                list.add(cb.like(root.get("username").as(String.class),"%"+user.getUsername()+"%"));
            }

            if(!StringUtils.isEmpty(roleName)){

                /**
                 * 這裡的join.get("name"),就是對應的Role.class裡面的name
                 */
                list.add(cb.like(join.get("name").as(String.class),"%"+roleName+"%"));
            }

            if(!StringUtils.isEmpty(user.getCreateTime())){

                /**
                 * 大於等於
                 */
                list.add(cb.greaterThanOrEqualTo(root.get("createTime").as(Timestamp.class),user.getCreateTime()));
            }

            if(!StringUtils.isEmpty(user.getUpdateTime())){

                /**
                 * 小於等於
                 */
                list.add(cb.lessThanOrEqualTo(root.get("createTime").as(Timestamp.class),user.getUpdateTime()));

            }

            Predicate[] p = new Predicate[list.size()];
            return cb.and(list.toArray(p));
        }
    }
}

查詢測試

1、新增測試資料

    @Test
    public void test3() {

        /**
         * 新增角色
         */
        Role role = new Role();
        role.setName("測試角色");
		role = roleRepo.save(role);

        /**
         * 新增並繫結角色
         */
        User user = new User("小李",20,"男",role);
        User user1 = new User("小花",21,"女",role);
        
        userRepo.save(user);
        userRepo.save(user1);
    }

檢視資料都已經新增成功了,並且createTime和updateTime也幫我們加上了

2、簡單查詢

    @Test
    public void Test4(){

        /**
         * 新增查詢資料,模糊查詢使用者名稱
         */
        User user = new User();
        user.setUsername("花");
        List<User> users = userQueryService.queryAll(user);
        users.forEach(user1 -> {
            System.out.println(user1.toString());
        });
    }

執行結果如下

3、分頁+關聯查詢

    @Test
    public void test5() {

        //頁碼,Pageable中預設是從0頁開始
        int page = 0;
        //每頁的個數
        int size = 10;
        Sort sort = new Sort(Sort.Direction.DESC,"id");
        Pageable pageable = PageRequest.of(page,size,sort);

        Page<User> users = userQueryService.queryAll(new User(),pageable,"測試角色");

        System.out.println("總資料條數:"+users.getTotalElements());
        System.out.println("總頁數:"+users.getTotalPages());
        System.out.println("當前頁數:"+users.getNumber());

        users.forEach(user1 -> {
            System.out.println(user1.toString());
        });

    }
}

通過角色的名稱查詢使用者,執行結果如下

專案原始碼

github:https://github.com/dqjdda/SpringBoot_All

碼雲:https://gitee.com/hgpt/SpringBoot_All

開源後臺管理系統:

歡迎體驗Aurora

github: https://github.com/dqjdda/Aurora

碼雲: https://gitee.com/hgpt/Aurora