本文共 7783 字,大约阅读时间需要 25 分钟。
上篇文章介绍了 Repository接口的使用(),接下来重点掌握 Repository的CrudRepository子接口下的子接口。
在dao层的接口中定义方法,查询的方法:find或get或read开头,遵守一些规定:
Keyword | Sample | JPQL snippet |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Repository的子接口的使用时只需要 dao层继承该接口即可。
CrudRepository接口还有一个PagingAndSortingRepository子接口:
CrudRepository 主要提供CRUD功能。
PagingAndSortingRepository 提供进行分页和排序记录的方法。
1、CrudRepository 主要提供CRUD功能。
CrudRepository接口的方法:很好理解就不解释了,下面使用几个即可快速掌握。
public interface UserDao extends CrudRepository{}
测试:
@Test public void test() { User user = new User(); user.setUsername("赵云"); user.setPassword("123456"); user.setAge(18); user.setCreatetime(LocalDateTime.now()); User save = userDao.save(user); System.out.println(save.getId()); // 4 } @Test public void testList() { Listlist = new ArrayList<>(); for (int i = 0; i < 20; i++) { User user = new User(); user.setUsername("赵云" + i); user.setPassword("123456"); user.setAge(18 + i); user.setCreatetime(LocalDateTime.now()); list.add(user); } List saveAll = (List ) userDao.saveAll(list); // id 不存在,会报错:org.springframework.dao.EmptyResultDataAccessException: // No class cn.jq.springdatajpademo.model.User entity with id 2 exists! userDao.deleteById(2L); }
2、PagingAndSortingRepository 提供进行分页和排序记录的方法。
Pageable是一个接口,这里使用 PageRequest类
测试:
@Test public void test() { Sort.Order order1 = new Sort.Order(Sort.Direction.ASC, "age"); Sort.Order order2 = new Sort.Order(Sort.Direction.DESC, "id"); Sort sort = Sort.by(order1, order2); // 查询第3页 Pageable pageRequest = PageRequest.of(2, 10, sort); Pagepage = userDao.findAll(pageRequest); List userList = page.getContent(); // 数据 int number = page.getNumber(); // 当前页码,注意默认从0开始 int totalPages = page.getTotalPages(); // 总页码数 int numberOfElements = page.getNumberOfElements(); // 当前页码记录数 long totalElements = page.getTotalElements(); // 总的数量 int size = page.getSize(); // 每页的记录数 System.out.println("userList = " + userList); System.out.println("number = " + number + 1); System.out.println("totalPages = " + totalPages); System.out.println("numberOfElements = " + numberOfElements); System.out.println("totalElements = " + totalElements); System.out.println("size = " + size); }
3、JpaRepository接口是项目开发时使用最多的接口。
JpaRepository继承自PagingAndSortingRepository接口,JpaRepository基于JPA的Repository接口,极大减少了JPA作为数据访问的代码,JpaRepository是实现Spring Data JPA技术访问数据库的关键接口。
public interface UserDao extends JpaRepository{}
测试:
@Test public void test() { User user = new User(); user.setUsername("赵云胜多负少"); user.setPassword("123456"); user.setAge(18); user.setCreatetime(LocalDateTime.now());// 主键存在update,不存在就insert操作// user.setId(4L); User saveAndFlush = userDao.saveAndFlush(user); System.out.println(saveAndFlush.getId()); }
JpaSpecificationExecutor 是 JPA 2.0 提供的 Criteria API 的使用封装,可以用于动态生成 Query 来满足我们业务中的各种复杂场景。
Spring Data JPA 为我们提供了 JpaSpecificationExecutor 接口。该接口通过Specification来定义查询条件,使用Specification的要点就是CriteriaBuilder,通过这个对象来创建条件,之后返回一个Predicate对象。这个对象中就有了相应的查询需求,我们同样可以定义多个Specification,之后通过Specifications对象将其连接起来。
通过源码看出:SimpleJpaRepository类是JpaSpecificationExecutor接口的默认实现。
测试:
public interface UserDao extends JpaRepository, JpaSpecificationExecutor {}
@Test public void test() { Specifications1 = new Specification () { /** * @param *root: 代表查询的实体类. * @param criteriaQuery: 可以从中可到 Root 对象, 即告知 JPA Criteria 查询要查询哪一个实体类. 还可以 * 来添加查询条件, 还可以结合 EntityManager 对象得到最终查询的 TypedQuery 对象.使用不多 * @param *criteriaBuilder: CriteriaBuilder 对象. 用于创建 Criteria 相关对象的工厂. 当然可以从中获取到 Predicate 对象 * @return: *Predicate 类型, 代表一个查询条件. */ @Override public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { Path age = root.get("age"); Predicate p1 = criteriaBuilder.greaterThan(age, 18); Path username = root.get("username"); Predicate p2 = criteriaBuilder.like(username, "%李四%"); // where user0_.age>18 and ( user0_.username like ? ) return criteriaBuilder.and(p1, p2); } }; List list1 = userDao.findAll(s1); System.out.println(list1); }
如果SpringData提供的JPA接口没有我们需要的查询方式,也是可以自定义Repository接口的。
spring data除了已经给我们提供了大量的 Repository接口,它支持我们自己定义Repository接口来扩展功能,实现一些个性化的需求。
1、自定义Repository接口的具体步骤:
1)新建一个自定义接口
// 自定义 Repository接口public interface MyUserRepository { ListfindByAge(Integer age);}
2)新建该自定义接口的实现类,并对方法进行实现,需要注入 EntityManager对象完成对数据库的操作
public class MyUserRepositoryImpl implements MyUserRepository { // 这里使用JPA技术实现 @PersistenceContext private EntityManager entityManager; @Override public ListfindByAge(Integer age) { String jpql = "select u from User u where u.age <= ?1"; Query query = entityManager.createQuery(jpql, User.class); query.setParameter(1, age); List resultList = query.getResultList(); return resultList; }}
注意:实现类的名称必须是该自定义接口的名称+Impl,名称会由SpringData解析。
EntityManager是JPA中用于增删改查的接口,它的作用相当于一座桥梁,连接内存中的 Java对象和数据库的数据存储。也可以根据它进行sql的原生查找。
3)在目标接口(dao层接口)中继承该自定义接口。
public interface UserDao extends JpaRepository, MyUserRepository { // spring data jpa 方法 List findUsersByUsernameLikeAndAgeLessThanEqual(String username, Integer age);}
4)测试类,目标接口(dao层接口)就可以使用自定义接口方法
@Test public void testList() { ListuserList = userDao.findByAge(18); System.out.println(userList); List userList2 = userDao.findUsersByUsernameLikeAndAgeLessThanEqual("%赵云%", 18); System.out.println(userList2); }
参考文章:
—— Stay Hungry. Stay Foolish. 求知若饥,虚心若愚。
转载地址:http://lgdgn.baihongyu.com/