目录
一.概述
二.方法名元素
三.属性表达式
四.分页和排序
五.TopN的取得
Spring Data的Repository接口提供了通过方法名称自动生成查询逻辑的能力。
在Spring Data Neo4j中,继承Neo4jRepository接口同样可以获得这种按方法名自动生成查询逻辑的功能。
查询的默认深度为1,即查询本节点以及和本节点有直接关系的节点,查询的关系类型为节点实体类(使用@NodeEntity注解)中定义的关系类型。可以使用@Depth注解直接改变当前方法的查询深度,也可以使用(@Depth int depth)定义为方法的一个参数,根据传入参数决定查询深度,0为只查询本节点不查询关系,-1为无限延申。
package com.study.neo4j.dao; import org.springframework.data.neo4j.repository.Neo4jRepository; import com.study.neo4j.bean.node.Person; public interface PersonRepository extends Neo4jRepository<Person,Long> { //@Depth(value=2) Person findByName(String name); }该机制从方法中剥离前缀find…By、read…By、query…By、count…By和get…By,并开始解析其余部分。 方法名称可以包含表达式,比如Distinct。 第一个By充当分隔符,其后为查询条件。 可以使用And和Or连接多个属性的条件。 默认是相等比较,也可以使用Between, LessThan, GreaterThan,Like,Containing等比较方式。 可以使用IgnoreCase忽略单个属性的大小写或者AllIgnoreCase忽略所有属性的大小写。 可以使用OrderBy做排序,使用Asc和Desc指定排序方向。 示例如下:
// 返回 属性lastname=参数1 的记录条数 long countByLastname(String lastname); // 删除 属性lastname=参数1 的记录并返回删除条数 long deleteByLastname(String lastname); // 删除 属性lastname=参数1 的记录并返回删除的记录 List<User> removeByLastname(String lastname); // 返回 属性lastname=参数1 的记录 List<Person> findByLastname(String lastname); // 返回 属性emailAddress=参数1 并且 属性lastname=参数2 的记录 List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname); // 返回 属性lastname=参数1 或者 属性firstname=参数2 的去重后的记录 List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname); List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname); // 返回 属性lastname=参数1(忽略大小写) 的记录 List<Person> findByLastnameIgnoreCase(String lastname); // 返回 属性lastname=参数1(忽略大小写) 并且 属性firstname=参数2(忽略大小写) 的记录 List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname); // 返回 属性lastname=参数1 的记录并按firstname升序排列 List<Person> findByLastnameOrderByFirstnameAsc(String lastname); // 返回 属性lastname=参数1 的记录并按firstname降序排列 List<Person> findByLastnameOrderByFirstnameDesc(String lastname);属性表达式的自动解析,比如 List<Person> findByAddressZipCode(ZipCode zipCode); 在解析的时候,按照骆驼命名法进行从右往左的拆分,并依次判断是否存在,如果存在就使用,如果不存在再次重新拆分。 第一步 拆分为AddressZip和Code,判断类结构是不是 x.addressZip.code,如果是就停止,否者进行第二部判断 第二步 拆分为Address和ZipCode,判断类结构是不是 x.address.zipCode,如果是就停止,否者继续...... 这种方法在多数情况下结果是对的,但有时候也会出错,比如既存在 x.address又存在 x.addressZip 的时候,就自动选择了addressZip的分支。 为了避免这种情况,可以使用"_"做强制分割。 List<Person> findByAddress_ZipCode(ZipCode zipCode); 在解析的时候就会匹配 x.address的结构
Pageable和Sort可以用来自动分页和排序。
Page<User> findByLastname(String lastname, Pageable pageable); Slice<User> findByLastname(String lastname, Pageable pageable); List<User> findByLastname(String lastname, Sort sort); List<User> findByLastname(String lastname, Pageable pageable);• Pageable和Sort不支持NULL值,如果要指定不分页和不排序可以使用Sort.unsorted()和Pageable.unpaged()对象。 • Pageable的属性里包含Sort • 返回Page和Slice的处理是不一样。 返回Page的时候,会额外多发行一个count的查询来统计全体件数,可以让Page对象知道全体件数和分页数。 Page的实际查询会取当前分页的数据,而Slice的实际查询会取当前分页的每页件数+1件,多出来的一件用来判断Slice是否有后续数据hasNext()
// 简单的生成Sort Sort sort = Sort.by("firstname").ascending() .and(Sort.by("lastname").descending()); // 类型安全的方式生成Sort TypedSort<Person> person = Sort.sort(Person.class); Sort sort = person.by(Person::getFirstname).ascending() .and(person.by(Person::getLastname).descending());这是Spring Data的机能定义,在Spring Data Neo4j里面不支持,可能是因为neo4j里没有top和first语法吧。
// 取得第一件 User findFirstByOrderByLastnameAsc(); // 取得第一件 User findTopByOrderByAgeDesc(); // 取得分页的前10件 Page<User> queryFirst10ByLastname(String lastname, Pageable pageable); // 取得分页的前3件 Slice<User> findTop3ByLastname(String lastname, Pageable pageable); // 取得前10件 List<User> findFirst10ByLastname(String lastname, Sort sort); // 取得分页的前10件 List<User> findTop10ByLastname(String lastname, Pageable pageable);