返回介绍

11.3 扩展数据存取的功能

发布于 2025-04-26 13:26:37 字数 3827 浏览 0 评论 0 收藏

使用数据库是应用系统最基本的功能需求,同时也是最频繁和最复杂的功能需求。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);
    }

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。