《深入实践Spring Boot》一2.4 使用Neo4j

本节书摘来自华章出版社《深入实践Spring Boot》一书中的第2章,第2.14节,作者陈韶健,更多章节内容可以访问“华章计算机”公众号查看。

2.4 使用Neo4j

有没有既具有传统关系型数据库的优点,又具备NoSQL数据库优势的一种数据库呢?Neo4j就是一种这样的数据库。Neo4j是一个高性能的NoSQL图数据库,并且具备完全事务特性。Neo4j将结构化数据存储在一张图上,图中每一个节点的属性表示数据的内容,每一条有向边表示数据的关系。Neo4j没有表结构的概念,它的数据用节点的属性来表示。

2.4.1 Neo4j依赖配置

在Spring Boot中使用Neo4j非常容易,因为有spring-data-neo4j提供了强大的支持。首先,在工程的Maven管理中引入Neo4j的相关依赖,如代码清单2-20所示。
代码清单2-20 使用Neo4j的Maven依赖配置

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-rest</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-neo4j</artifactId>
        <version>4.0.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>com.voodoodyne.jackson.jsog</groupId>
        <artifactId>jackson-jsog</artifactId>
        <version>1.1</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

2.4.2 节点和关系实体建模

虽然Neo4j没有表结构的概念,但它有节点和关系的概念。例如,现在有演员和电影两个实体,它们的关系表现为一个演员在一部电影中扮演一个角色。那么就可以创建演员和电影两个节点实体,和一个角色关系实体。它们的实体-关系模型如图2-5所示。

3

这个实体-关系模型的定义比起关系型数据库的实体-关系模型的定义要简单得多,但是它更加形象和贴切地表现了实体之间的关系。更难能可贵的是,这个实体-关系模型是可以不经过任何转换而直接存入数据库的,也就是说,在Neo4j图数据库中保存的数据与图2-5所示的相同,它仍然是一张图。这对于业务人员和数据库设计人员来说,它的意义相同。所以使用Neo4j数据库,将在很大程度上减轻了设计工作和沟通成本。
像JPA使用了ORM一样,Neo4j使用了对象-图形映射(Object-Graph Mapping,OGM)的方式来建模。代码清单2-21是演员节点实体建模,使用注解@JsonIdentityInfo是防止查询数据时引发递归访问效应,注解@NodeEntity标志这个类是一个节点实体,注解@GraphId定义了节点的一个唯一性标识,它将在创建节点时由系统自动生成,所以它是不可缺少的。这个节点预定义了其他两个属性,name和born。节点的属性可以随需要增加或减少,这并不影响节点的使用。
代码清单2-21 演员节点实体建模

@JsonIdentityInfo(generator=JSOGGenerator.class)
@NodeEntity
public class Actor {
    @GraphId Long id;
    private String name;
    private int born;

    public Actor() { }

代码清单2-22是电影节点实体建模,注解@Relationship表示List是一个关系列表,其中type设定了关系的类型,direction设定这个关系的方向,Relationship.INCOMING表示以这个节点为终点。addRole定义了增加一个关系的方法。
代码清单2-22 电影节点实体建模

@JsonIdentityInfo(generator=JSOGGenerator.class)
@NodeEntity
public class Movie {
    @GraphId Long id;
    String title;
    String year;
    String tagline;
    @Relationship(type="ACTS_IN", direction = Relationship.INCOMING)
    List<Role> roles = new ArrayList<>();

public Role addRole(Actor actor, String name){
    Role role = new Role(actor,this,name);
    this.roles.add(role);
    return role;
}

public Movie() { }

代码清单2-23是角色的关系实体建模,注解@RelationshipEntity表明这个类是一个关系实体,并用type指定了关系的类型,其中@StartNode指定起始节点的实体,
@EndNode指定终止节点的实体,这说明了图中一条有向边的起点和终点的定义。其中定义了一个创建关系的构造函数Role(Actor actor,Movie movie,String name),这里的name参数用来指定这个关系的属性。
代码清单2-23 角色关系实体建模

@JsonIdentityInfo(generator=JSOGGenerator.class)
@RelationshipEntity(type = "ACTS_IN")
public class Role {
    @GraphId
    Long id;
    String role;
    @StartNode
    Actor actor;
    @EndNode
    Movie movie;

    public Role() {
    }

    public Role(Actor actor, Movie movie, String name) {
        this.actor = actor;
        this.movie = movie;
        this.role = name;
    }

2.4.3 节点实体持久化

像对其他数据库的访问和存取等操作一样,spring-data-neo4j提供了功能丰富的资源库可供调用,因此,对于演员和电影节点实体,可以创建它们对应的资源库接口,实现实体的持久化。代码清单2-24是电影资源库接口的定义,它继承于GraphRepository接口,实现了电影实体的持久化。使用相同方法可以对演员的节点实体实现持久化。关系实体却不用实现持久化,当保存节点实体时,节点实体的关系将会同时保存。
代码清单2-24 电影实体持久化
@Repository
public interface MovieRepository extends GraphRepository {
Movie findByTitle(@Param("title") String title);
}
其中GraphRepository接口的继承关系也遵循了Spring Boot资源库定义的规则,即使用与JPA相同的标准规范,所以它同样包含使用数据库的丰富功能,如图2-6所示。

2.4.4 Neo4j测试

代码清单2-24是Neo4j的数据库配置类,其中@Enable-TransactionManagement启用了事务管理,@EnableNeo4jRe-positories启用了Neo4j资源库并指定了我们定义的资源库接口的位置,在重载的SessionFactory函数中设定了定义实体的位置,这将促使定义的实体被作为域对象导入,RemoteServer设定连接Neo4j服务器的URL、用户名和密码,这些参数要依据安装Neo4j服务器的情况来设置。如果还没有安装Neo4j服务器,可参考附录A的方法进行安装,安装完成后启动服务器以备使用。
代码清单2-25 Neo4j配置类

@Configuration
@EnableTransactionManagement
@EnableNeo4jRepositories(basePackages = { "dbdemo.neo4j.repositories" })
public class Neo4jConfig extends Neo4jConfiguration {
    @Override
    public Neo4jServer neo4jServer() {
        return new RemoteServer("http://192.168.1.221:7474","neo4j","12345678");
    }

@Override
public SessionFactory getSessionFactory() {
    return new SessionFactory("dbdemo.neo4j.domain");
}

}
现在可以编写一个测试程序来验证和演示上面编写的代码的功能,如代码清
单2-26所示。这个测试程序分别创建了三部电影和三个演员,以及三个演员在三部电影中各自扮演的角色,然后按照电影标题查出一部电影,按照其内在的关系输出这部电影的信息和每个演员扮演的角色。这些数据的内容参照了Neo4j帮助文档中提供的示例数据。
代码清单2-26 使用Neo4j的JUint测试程序

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {Neo4jConfig.class})
public class MovieTest {
    private static Logger logger = LoggerFactory.getLogger(MovieTest.class);

@Autowired
MovieRepository movieRepository;

@Before
public void initData(){
    movieRepository.deleteAll();

    Movie matrix1 = new Movie();
    matrix1.setTitle("The Matrix");
    matrix1.setYear("1999-03-31");

    Movie matrix2 = new Movie();
    matrix2.setTitle("The Matrix Reloaded");
    matrix2.setYear("2003-05-07");

    Movie matrix3 = new Movie();
    matrix3.setTitle("The Matrix Revolutions");
    matrix3.setYear("2003-10-27");

    Actor keanu = new Actor();
    keanu.setName("Keanu Reeves");

    Actor laurence = new Actor();
    laurence.setName("Laurence Fishburne");

    Actor carrieanne = new Actor();
    carrieanne.setName("Carrie-Anne Moss");

    matrix1.addRole(keanu,  "Neo");
    matrix1.addRole(laurence, "Morpheus");
    matrix1.addRole(carrieanne,  "Trinity");
    movieRepository.save(matrix1);
    Assert.notNull(matrix1.getId());

    matrix2.addRole(keanu, "Neo");
    matrix2.addRole(laurence, "Morpheus");
    matrix2.addRole(carrieanne,  "Trinity");
    movieRepository.save(matrix2);
    Assert.notNull(matrix2.getId());

    matrix3.addRole(keanu, "Neo");
    matrix3.addRole(laurence, "Morpheus");
    matrix3.addRole(carrieanne, "Trinity");
    movieRepository.save(matrix3);
    Assert.notNull(matrix3.getId());
}

@Test
public void get(){
    Movie movie = movieRepository.findByTitle("The Matrix");
    Assert.notNull(movie);
    logger.info("===movie=== movie:{}, {}",movie.getTitle(), movie.getYear());
    for(Role role : movie.getRoles()){
        logger.info("====== actor:{}, role:{}", role.getActor().getName(), role.getRole());
    }
}

}
在IDEA的Run/Debug Conf?iguration配置中增加一个JUint的配置项目,模块选择neo4j,工作目录选择模块所在的根目录,测试程序选择MovieTest这个类,并将配置保存为neo4jtest。
使用Debug模式运行测试项目neo4jtest,如果测试通过,将在控制台中看到输出查询的这部电影和所有演员及其扮演的角色,如下所示:
=== movie=== movie:The Matrix, 1999-03-31
====== actor:Keanu Reeves, role:Neo
====== actor:Laurence Fishburne, role:Morpheus
====== actor:Carrie-Anne Moss, role:Trinity
这时,在数据库客户端的控制台上,单击左面侧边栏的关系类型ACTS_IN,可以看到一个很酷的图形,图中每部电影和每个演员是一个节点,节点的每条有向边代表了这个演员在那部电影中扮演的角色,如图2-7所示。

时间: 2024-09-15 19:21:15

《深入实践Spring Boot》一2.4 使用Neo4j的相关文章

《深入实践Spring Boot》一第3章 Spring Boot界面设计3.1 模型设计

本节书摘来自华章出版社<深入实践Spring Boot>一书中的第3章,第3.1节,作者陈韶健,更多章节内容可以访问"华章计算机"公众号查看. 第3章 Spring Boot界面设计 用Spring Boot框架设计Web显示界面,我们还是使用MVC(Model View Controller,模型-视图-控制器)的概念,将数据管理.事件控制和界面显示进行分层处理,实现多层结构设计.界面设计,即视图的设计,主要是组织和处理显示的内容,界面上的事件响应最终交给了控制器进行处理

《深入实践Spring Boot》一2.3 使用MongoDB

本节书摘来自华章出版社<深入实践Spring Boot>一书中的第2章,第2.3节,作者陈韶健,更多章节内容可以访问"华章计算机"公众号查看. 2.3 使用MongoDB 在当前流行的NoSQL数据库中,MongoDB是大家接触比较早而且用得比较多的数据库.MongoDB是文档型的NoSQL数据库,具有大数据量.高并发等优势,但缺点是不能建立实体关系,而且也没有事务管理机制. 2.3.1 MongoDB依赖配置 在Spring Boot中使用MongoDB也像使用JPA一样

《深入实践Spring Boot》一3.2 控制器设计

本节书摘来自华章出版社<深入实践Spring Boot>一书中的第3章,第3.2节,作者陈韶健,更多章节内容可以访问"华章计算机"公众号查看. 3.2 控制器设计 怎样将视图上的操作与模型--数据管理模块联系起来,这中间始终是控制器在起着通信桥梁的作用,它响应视图上的操作事件,然后根据需要决定是否访问数据管理模块,最后再将结果返回给合适的视图,由视图处理显示.下面将按照电影控制器的设计来说明控制器中增删查改的实现方法,演员控制器的设计与此类似,不再赘述. 3.2.1 新建控

深入实践Spring Boot导读

Preface?前 言 Spring Boot作为Java编程语言的一个全新开发框架,在国内外才刚刚兴起,还未得到普及使用.相比于以往的一些开发框架,Spring Boot不但使用更加简单,而且功能更加丰富,性能更加稳定而健壮.使用Spring Boot开发框架,不仅能提高开发速度,增强生产效率,从某种意义上,可以说是解放了程序员的劳动,而且一种新技术的使用,更能增强系统的稳定性和扩展系统的性能指标.本书就是本着提高开发效率,增强系统性能,促进新技术的普及使用这一目的而写的. Spring Bo

《深入实践Spring Boot》一第一部分 Part 1基础应用开发

第一部分 Part 1 基础应用开发 第1章 Spring Boot入门 第2章 在Spring Boot中使用数据库 第3章 Spring Boot界面设计 第4章 提高数据库访问性能 第5章 Spring Boot安全设计 这一部分从搭建开发环境,简单入门,到使用数据库.界面设计.安全管理等一系列内容,介绍了使用Spring Boot框架进行基础应用开发的方法. 第1章介绍了开发环境的搭建和开发工具的选择和安装,并以一个非常简单的实例,演示了如何使用Spring Boot框架创建工程和发布应

《深入实践Spring Boot》一导读

Preface前 言 Spring Boot作为Java编程语言的一个全新开发框架,在国内外才刚刚兴起,还未得到普及使用.相比于以往的一些开发框架,Spring Boot不但使用更加简单,而且功能更加丰富,性能更加稳定而健壮.使用Spring Boot开发框架,不仅能提高开发速度,增强生产效率,从某种意义上,可以说是解放了程序员的劳动,而且一种新技术的使用,更能增强系统的稳定性和扩展系统的性能指标.本书就是本着提高开发效率,增强系统性能,促进新技术的普及使用这一目的而写的. Spring Boo

《深入实践Spring Boot》一第1章Spring Boot入门1.1 配置开发环境

第1章 Spring Boot入门 在使用Spring Boot框架进行各种开发体验之前,要先配置好开发环境.首先安装JDK,然后选择一个开发工具,如Eclipse IDE和IntelliJ IDEA(以下简称IDEA)都是不错的选择.对于开发工具的选择,本书极力推荐使用IDEA,因为它为Spring Boot提供了许多更好和更贴切的支持,本书的实例都是使用IDEA创建的.同时,还需要安装Apache Maven和Git客户端.所有这些都准备好之后,我们就能开始使用Spring Boot了. 1

《深入实践Spring Boot》一第2章 在Spring Boot中使用数据库2.1 使用MySQL

第2章 在Spring Boot中使用数据库 使用数据库是开发基本应用的基础.借助于开发框架,我们已经不用编写原始的访问数据库的代码,也不用调用JDBC(Java Data Base Connectivity)或者连接池等诸如此类的被称作底层的代码,我们将在高级的层次上访问数据库.而Spring Boot更是突破了以前所有开发框架访问数据库的方法,在前所未有的更加高级的层次上访问数据库.因为Spring Boot包含一个功能强大的资源库,为使用Spring Boot的开发者提供了更加简便的接口进

深入实践Spring Boot》一2.5 小结

2.5 小结 这一章,我们一口气学习使用了4种数据库:MySQL.Redis.MongoDB.Neo4j,除了Redis以外,都使用了由Spring Boot提供的资源库来访问数据库并对数据库执行了一般的存取操作.可以看出,在Spring Boot框架中使用数据库非常简单.容易,这主要得益于Spring Boot资源库的强大功能,Spring Boot资源库整合了第三方资源,它把复杂的操作变成简单的调用,它把所有"辛苦.繁重的事情"都包揽了,然后将"微笑和鲜花"献给