SpringDataJpa(四):四种特殊的查询方法

27 篇文章 0 订阅
5 篇文章 0 订阅

SpringDataJpa

使用jpql查询

使用方法:
1)在dao接口中定义一个方法。使用方法的参数设置jpql的参数,使用方法的返回值接收查询结果。
2)在方法上添加一个@Query注解。
3)在注解中编写jpql。
4)测试

一、使用jpql查询全部

public interface CustomerDao extends JpaRepository<Customer,Long> {

    @Query("from Customer")
    List<Customer> getAllCustomer();
}
@Test
    public void find7() {
        List<Customer> allCustomer = customerDao.getAllCustomer();
        for (Customer customer : allCustomer) {
            System.out.println(customer);
        }
    }

二、查询分页
在查询方法中添加一个Pageable参数

@Query("from Customer")
List<Customer> getAllCustomerByPage(Pageable pageable);
@Test
    public void find8() {
        List<Customer> allCustomer = customerDao.getAllCustomerByPage(new PageRequest(0,5));
        for (Customer customer : allCustomer) {
            System.out.println(customer);
        }
    }

三、jpql查询带参数

根据id查询

@Query("from Customer where custId = ?")
Customer getCustomerById(long id);
@Test
    public void find9() {
        Customer customer = customerDao.getCustomerById(100l);
        System.out.println(customer);
    }

根据客户名称和地址进行模糊查询

  • sql:SELECT * FROM cst_customer WHERE cust_name LIKE '%王%' and cust_address LIKE '%浙江%'
  • jpql:from Customer where custName like ? and custAddress like ?

注意:参数与问号需要进行顺序对应

@Query("from Customer where custName like ? and custAddress like ?")
List<Customer> getCustomerByNameAndAddress(String name,String address);
@Test
    public void find10() {
        List<Customer> customerList = customerDao.getCustomerByNameAndAddress("%王%", "%浙江%");
        for (Customer customer : customerList) {
            System.out.println(customer);
        }
    }

如果就想要反着写,则可以进行参数的顺序标记

@Query("from Customer where custName like ?2 and custAddress like ?1")
List<Customer> getCustomerByNameAndAddress(String address,String name);

使用jpql更新

可以执行更新、删除操作,不支持插入操作。

  • sql:UPDATE cst_customer set cust_source = '互联网' where cust_id = 100
  • jpql: update Customer set custSource = ? where custId = ?

使用方法:
1)在dao接口中定义一个方法。
2)在方法上添加@Query注解,在注解中编写jpql语句
3)在方法上添加@Modifying注解
4)测试

注意:

  • 自定义的jpql方法需要开启事务,且需要提交。
  • dao原本就有的方法里因为有@Transactional注解,所以不用加

方式一:在测试方法中加注解

@Query("update Customer set custSource = ? where custId = ?")
@Modifying
void updateSource(String source, long id);
@Test
@Transactional
@Commit
public void testUpdate() {
    customerDao.updateSource("互联网",100l);
}

方式二:在dao接口方法中加注解
注意:在测试方法中默认回滚,在dao方法中默认提交

@Query("update Customer set custSource = ? where custId = ?")
@Modifying
@Transactional
void updateSource(String source, long id);
@Test
    public void testUpdate() {
        customerDao.updateSource("互联网",100l);
    }

使用原生sql查询

不推荐使用原生的sql,但也可以用

使用方法:
1)在dao中定义一个方法
2)在方法上添加@Query注解
3)在注解中添加原生的sql语句,添加一个属性nativeQuery=true

@Query(value = "select * from cst_customer where cust_name like ?" , nativeQuery = true)
List<Customer> getAllCustomerBySQL(String name);
@Test
    public void find11() {
        List<Customer> customerList = customerDao.getAllCustomerBySQL("%王%");
        for (Customer customer : customerList) {
            System.out.println(customer);
        }
    }

方法命名规则查询(推荐使用)

通过一定的规则定义一个方法,框架就可以根据方法名生成一个sql语句进行查询。

规则:

  1. 应该使用findBy开头
  2. 查询某个字段,findBy后跟实体类的属性的名称,默认是等于
  3. 如果有多个条件,就在方法后加And+实体类的属性名。
  4. 方法的参数对应查询定义。
  5. 返回值根据返回的数据类型定义。

一、根据id查询

Customer findByCustId(long id);
@Test
    public void find12() {
        Customer customer = customerDao.findByCustId(100l);
        System.out.println(customer);
    }

二、两个条件的模糊查询

List<Customer> findByCustNameLikeAndCustAddressLike(String name, String address);
@Test
    public void find13() {
        List<Customer> customerList = customerDao.findByCustNameLikeAndCustAddressLike("%王%", "%浙江%");
        for (Customer customer : customerList) {
            System.out.println(customer);
        }
    }

三、分页查询
如果需要分页在方法中添加一个参数Pageable即可。

List<Customer> findByCustAddressLike(String address, Pageable pageable);
@Test
    public void find14() {
        List<Customer> customerList = customerDao.findByCustAddressLike("%浙江%", new PageRequest(0, 5));
        for (Customer customer : customerList) {
            System.out.println(customer);
        }
    }

获得page对象:直接返回类型写上Page即可

Page<Customer> findByCustAddressLike(String address, Pageable pageable);
@Test
    public void find14() {
        Page<Customer> page = customerDao.findByCustAddressLike("%浙江%", new PageRequest(0, 5));
        long totalElements = page.getTotalElements();
        int totalPages = page.getTotalPages();
        List<Customer> content = page.getContent();
        for (Customer customer : content) {
            System.out.println(customer);
        }
    }

使用Specification查询

Specification:说明书

除了原生sql,是最强大的查询方式,最复杂的查询方式。

使用方法

  1. 需要dao继承
    JpaSpecificationExecutor接口(接口可以多重继承)
  2. 使用JpaSpecificationExecutor接口中提供方法进行查询。每个方法都需要使用Specification对象作为参数。

JpaSpecificationExecutor接口
其中有三个方法:

  • findOne:查询一条记录
  • findAll:查询多条记录
  • count:统计记录数

Specification接口
只有一个toPredicate方法:
返回一个查询条件。在方法中应该创建一个查询条件并返回。
返回值Predicate:查询条件。
参数

  • Root:代表sql语句的根节点。相当于sql语句中from后的表名。
  • CriteriaQuery
    查询对象。sql语句中的关键字包含在其中。
where
order by
group by
having
  • CriteriaBuilder:工具对象。
    所有的条件的生成都是使用CriteriaBuilder。只要涉及判断都需要使用CriteriaBuilder对象。主要使用CriteriaBuilder创建条件。

一、根据id查询
sql:select * from cst_customer where cust_id = ?

接口上添加继承的接口

public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> {
}
@Test
    public void find15() {
        Customer customer = customerDao.findOne(new Specification<Customer>() {
            @Override
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                //参数1:字段名称
                //参数2:字段的值
                Predicate predicate = cb.equal(root.get("custId"), 100l);
                return predicate;
            }
        });
        System.out.println(customer);
    }

也可以使用lambda表达式来写

@Test
    public void find15() {
//        Customer customer = customerDao.findOne(new Specification<Customer>() {
//            @Override
//            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//                //参数1:字段名称
//                //参数2:字段的值
//                Predicate predicate = cb.equal(root.get("custId"), 100l);
//                return predicate;
//            }
//        });
        Customer customer = customerDao.findOne((root, query, cb) -> cb.equal(root.get("custId"), 100l));
        System.out.println(customer);
    }

二、根据客户名称和地址模糊查询

@Test
    public void find16() {
        customerDao.findAll(new Specification<Customer>() {
            @Override
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                //创建查询条件,根据名称模糊查询
                Predicate predicate1 = cb.like(root.get("custName"), "%王%");
                //创建查询条件,根据地址模糊查询
                Predicate predicate2 = cb.like(root.get("custAddress"), "%北京%");
                //组合两个条件
                Predicate predicate = cb.and(predicate1, predicate2);
                //返回
                return predicate;
            }
        }).forEach(c-> System.out.println(c));
    }

三、分页查询

@Test
    public void find17() {
        Page<Customer> page = customerDao.findAll(new Specification<Customer>() {
            @Override
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                //创建查询条件,根据名称模糊查询
                Predicate predicate1 = cb.like(root.get("custName"), "%王%");
                //创建查询条件,根据地址模糊查询
                Predicate predicate2 = cb.like(root.get("custAddress"), "%浙江%");
                //组合两个条件
                Predicate predicate = cb.and(predicate1, predicate2);
                //返回
                return predicate;
            }
        }, new PageRequest(0, 5));
        List<Customer> content = page.getContent();
        for (Customer customer : content) {
            System.out.println(customer);
        }
    }

四、排序
1、在findAll方法中添加Sort参数

@Test
    public void find18() {
        List<Customer> customerList = customerDao.findAll(new Specification<Customer>() {
            @Override
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicate = cb.like(root.get("custName"), "%王%");
                return predicate;
            }
        }, new Sort(Sort.Direction.DESC, "custId"));
        for (Customer customer : customerList) {
            System.out.println(customer);
        }
    }

2、在接口中添加排序,使用CriteriaQuery对象

@Test
    public void find19() {
        List<Customer> customerList = customerDao.findAll(new Specification<Customer>() {
            @Override
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicate = cb.like(root.get("custName"), "%王%");
                //添加排序条件
                Predicate result = query.where(predicate)
                        .orderBy(cb.desc(root.get("custId")))
                        .getRestriction();
                return result;

            }
        });
        for (Customer customer : customerList) {
            System.out.println(customer);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值