- 前言
- 第一部分 基础应用开发
- 第 1 章 Spring Boot 入门
- 第 2 章 在 Spring Boot 中使用数据库
- 第 3 章 Spring Boot 界面设计
- 第 4 章 提高数据库访问性能
- 第 5 章 Spring Boot 安全设计
- 第二部分 分布式应用开发
- 第 6 章 Spring Boot SSO
- 第 7 章 使用分布式文件系统
- 第 8 章 云应用开发
- 第 9 章 构建高性能的服务平台
- 第三部分 核心技术源代码分析
- 第 10 章 Spring Boot 自动配置实现原理
- 第 11 章 Spring Boot 数据访问实现原理
- 第 12 章 微服务核心技术实现原理
- 附录 A 安装 Neo4j
- 附录 B 安装 MongoDB
- 附录 C 安装 Redis
- 附录 D 安装 RabbitMQ
- 结束语
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
11.3 扩展数据存取的功能
使用数据库是应用系统最基本的功能需求,同时也是最频繁和最复杂的功能需求。Spring Boot 始终以使用简单为基准,提供了一套以 JPA 的标准规范来设计的数据存取方法,虽然功能相当强大,但往往不能适合一些复杂的功能需求,这就需要对数据存取的功能做一些扩展。了解 Spring Boot 使用数据库的实现原理之后,要扩展数据存取的功能就比较容易了。
11.3.1 扩展 JPA 功能
根据数据库持久化的原理,可以扩展数据存取的功能,例如在第 4 章中,实现了扩展 JPA 的功能,如代码清单 11-11 所示。数据库持久化的接口实现类 ExpandJpa-RepositoryImpl,它继承了 SimpleJpaRepository 的实现,扩展了 JPA 访问数据库的功能。
代码清单 11-11 扩展 JPA 实现类
public class ExpandJpaRepositoryImpl<T,ID extends Serializable> extends Simple JpaRepository<T,ID> implements ExpandJpaRepository<T,ID> { private final EntityManager entityManager; private final JpaEntityInformation<T, ?> entityInformation; public ExpandJpaRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) { super(entityInformation, entityManager); this.entityManager = entityManager; this.entityInformation = entityInformation; } ...... }
11.3.2 扩展 Neo4j 功能
遵循 JPA 标准规范来设计,这对于新型的 Neo4j 数据库来说是一个挑战。在 JPA 中,可以使用如下定义来执行一个分页的查询:
@Query("select t from User t where t.name like :name") Page<User> findByName(@Param("name") String name, Pageable pageRequest);
但是这种方法对于 Neo4j 来说,却会导致严重的错误,如下定义是无法被正常执行的:
@Query("MATCH (m:Movie) WHERE m.name =~ ('(?i).*'+{name}+'.*') RETURN m") Page<Movie> findByName(@Param("name") String name, Pageable pageable);
所以为了实现这种分页查询,需要编写一个全局扩展类来实现,如代码清单 11-12 所示,它调用了 Neo4j 的底层实现方法 org.neo4j.ogm.session.Session 来执行分页查询。
代码清单 11-12 Neo4j 分页查询服务类
@Service public class PagesService<T> { @Autowired private Session session; public Page<T> findAll(Class<T> clazz, Pageable pageable, Filters filters){ Collection data = this.session.loadAll(clazz, filters, convert(pageable. getSort()), new Pagination(pageable.getPageNumber(), pageable.getPageSize()), 1); return updatePage(pageable, new ArrayList(data)); } private Page<T> updatePage(Pageable pageable, List<T> results) { int pageSize = pageable.getPageSize(); int pageOffset = pageable.getOffset(); int total = pageOffset + results.size() + (results.size() == pageSize?pageSize:0); return new PageImpl(results, pageable, (long)total); } private SortOrder convert(Sort sort) { SortOrder sortOrder = new SortOrder(); if(sort != null) { Iterator var3 = sort.iterator(); while(var3.hasNext()) { Sort.Order order = (Sort.Order)var3.next(); if(order.isAscending()) { sortOrder.add(new String[]{order.getProperty()}); } else { sortOrder.add(SortOrder.Direction.DESC, new String[]{order. getProperty()}); } } } return sortOrder; } }
这样在进行分页查询时,就可以调用这个服务类,代码清单 11-13 是使用电影名称,分页查询电影列表的一个实现例子。
代码清单 11-13 使用分页查询服务类进行分页查询的例子
@Autowired private PagesService<Movie> pagesService; ...... @RequestMapping(value="/list") public Page<Movie> list(HttpServletRequest request) throws Exception{ String name = request.getParameter("name"); String page = request.getParameter("page"); String size = request.getParameter("size"); Pageable pageable = new PageRequest(page==null? 0: Integer.parseInt(page), size==null? 10:Integer.parseInt(size), new Sort(Sort.Direction.DESC, "id")); Filters filters = new Filters(); if (!StringUtils.isEmpty(name)) { Filter filter = new Filter("name", name); filters.add(filter); } return pagesService.findAll(Movie.class, pageable, filters); }
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论