那就写在前面吧
上一篇博文中我们介绍了Neo4j独特的查询语言Cypher的用法,了解了Cypher的用法之后,我们就可以自行安装Neo4j然后在其自带的浏览器客户端使用Cypher查询了。
默认的访问地址是:http://localhost:7474/,通过这种方式我们就能比较直观的查看查询结果。但是在实际的项目中,这种方式只能作为辅助,我们实际要操作Neo4j有两种主要的方式:java API、Spring Data Neo4j。使用java API的方式比较繁琐,因此我们主要还是用Spring Data Neo4j来访问图数据库。
Spring Data Neo4j简介
Spring Data Neo4j是一个对象-图形映射(OGM) 框架,是为了简化开发者的工作而创建的(目前只有Java具有),或者说是满足那些需要或者想要用它与基于POJO域模型工作的开发者,在这种情况下, 所有的数据都存储在Neo4j中。
它的目的是通过处理所有低层工作和从Neo4j读域实体并写回去所必需的映射逻辑来提高效率。这将使你腾出时间把重点放在写代码上——即业务逻辑。
作为Spring Data的子项目之一,Spring Data Neo4j与其他的OGM框架一样,在项目中扮演着连接底层的Neo4j数据库与域模型的重要角色。具体的架构如下图所示:
注意:SDN不适合一次处理任意类型的大量数据的场景。要加载或存储的任何逻辑在一次操作中超过10000个单元对SDN来说不是一个好的选择。另外,通过提供了一个间接层,SDN会比仅仅使用核心API慢,因此,如果速度和性能是考虑的最重要因素的话,最好还是使用其本身的API。
建立模型
模型主要包含了节点与关系的信息,其中节点依然是在普通的POJO对象上加上Neo4j独有的注解来构建。
下面我们来看一个简单的节点例子,它表示一个作业Job
@NodeEntity
public class Job {
@GraphId
private Long id;
@Indexed
private String name;
private String description;
private String state;
private Job() {
// Empty constructor required as of Neo4j API 2.0.5
};
public Job(String name) {
this.name = name;
}
@Relationship(type = "DEPEND", direction = Relationship.UNDIRECTED)
public Set<Job> depends;
// getter and setter methods
。。。
}
@NodeEntity 注解用于标识它表示一个节点,用于类的前面
@GraphId 可以理解为Neo4j自动为节点生成的唯一性标识Id
@Indexed 用于节点的属性上,可以为该属性创建索引,提高其查询效率
关系实体的例子如下
@RelationshipEntity(type = "DEPEND")
public class depend {
@GraphId
private Long relationshipId;
@StartNode
Job startJob;
@EndNode
Job endJob;
private String property;
}
@RelationshipEntity 注解用于标识它表示一个节点,用于类的前面。使用type可以关联关系的名字"DEPEND"
@StartNode 表示关系的起始节点(关系出)
@EndNode 表示关系的终止节点(关系进)
上面的关系表示作业之间存在单向的依赖关系,这种比较简单的关系可以不用专门创建一个关系类来标识,像上面Job节点中定义的那样,我们可以使用一个注解来标识这种关系
@Relationship(type = "DEPEND", direction = Relationship.UNDIRECTED)
创建Repository
如何能与这些实体交互和怎样能加载并保存来自于或回到图形数据库中的POJO实体?
Spring Data Neo4j为我们提供了三种方式来实现。
① 支持Spring的配置
config入口做许多初始化工作,例如,可以将storeDirectory属性作为一个方便的方式来引用图形数据库(如果数据库不存在就创建一个新数据库)。在SDN 3.0以前的版本中,使用base-package属性指定域实体定义所在的目录或目录列表是强制性的。
② Neo4jTemplate类
Neo4jTemplate是一个SDN类,能用于实例化,可以直接使用或当Spring初始化时用于你的应用程序。通过充分利用具有依赖注入(DependencyInjection, DI)函数的Spring框架,我们可以更加专注于业务逻辑,而不用关心更多的样板代码(如样板事务代码)。
③ 资源库
Spring Data Neo4j为我们提供了资源库的方式来封装了常用的17种对模型的操作方法,比如保存、删除、按照id查询等等。我们要做的仅仅是创建一个接口,然后继承GraphRepository接口,就可以使用资源库中已经封装好的方法。
如果我们想要扩展资源库,那么就需要在我们的接口中编写新的业务方法来完成,这里可以使用注解@Query,然后编写具体的Cypher语句。
下面是一个例子:
public interface JobRepository extends GraphRepository<Job> {
Job findByName(@Param("name") String name);
// depth from 1 - 5,return job's name,path's length and node's name
// MATCH (n:Job) where n.name="PDM_F_T00_CNR_PARM" with n match p = (n) - [d:DEPEND*1..5] -> (m:Job) return m.name,length(p),extract(x in nodes(p) | x.name)
@Query("MATCH (n:Job) where n.name={name} with n match p = (n) - [d:DEPEND*1..5] -> (m:Job) return m")
Collection<Job> findDepthJob(@Param("name") String name);
}
可以看到在Cypher语句中是如何获取参数name的,使用{name}就可以获取下面方法中传入的name参数了。
小结
这篇博文主要介绍了Spring Data Neo4j如何使用来简化我们的开发,通过这几篇博文的介绍,我们已经了解了搭建一个简单的Neo4j项目所需要的必备知识。想要了解更多Neo4j以及Spring Data Neo4j的信息,请前往它们的官网查看其官方文档。