- 前言
- 第一部分 基础应用开发
- 第 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);
}
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论