Neo4j:入门基础(四)之Java API

Neo4j Java API

    Neo4j 提供 JAVA API 以编程方式执行所有数据库操作。它支持两种类型的API:

            1、Neo4j 原生的 Java API

            2、Neo4j Cypher Java API

    Neo4j 原生 Java API 是一种低级别的纯 JAVA API,用于执行数据库操作。Neo4j Cypher Java API 是简单而强大的 JAVA API,用于执行所有CQL命令以执行数据库操作。

Neo4j:入门基础(四)之Java API_第1张图片

 

环境配置

    CentOS  6.9

    Neo4j  3.5.3  [安装教程]

    IDEA  2018.1  [安装教程]

    Maven  3.1.1 [安装教程]

 

实验

    1. 创建SpringBoot项目 

        因为Neo4j依赖的jar包比较多,所以推荐使用Maven来管理。

Neo4j:入门基础(四)之Java API_第2张图片

Neo4j:入门基础(四)之Java API_第3张图片 这步不操作也行,因为我们将使用Neo4j内嵌模式

 

 

        在 pom.xml 中添加依赖


    org.neo4j
    neo4j
    3.5.3

 

    2. 新建一个Java类 Neo4jNativeJavaAPI

Neo4j:入门基础(四)之Java API_第4张图片

    3. 导入需要的库包

import java.io.File;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;

        或者

import java.io.File;

import org.neo4j.graphdb.*;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;

    4. 无论是创建一个新的数据库,还是打开一个已有的数据库,首先都需要创建一个GraphDatabaseService实例

// GraphDatabaseService实例可以被多个线程共享,但是一个数据库只允许有一个Service实例 
GraphDatabaseService graphDB = new GraphDatabaseFactory().newEmbeddedDatabase( DB_PATH );

        可以对数据库进行一些配置(更多配置信息可以看GraphDatabaseSettings类的文档

GraphDatabaseService graphDB = new GraphDatabaseFactory()
    .newEmbeddedDatabaseBuilder( testDirectory.graphDbDir() )
    .setConfig( GraphDatabaseSettings.pagecache_memory, "512M" )
    .setConfig( GraphDatabaseSettings.string_block_size, "60" )
    .setConfig( GraphDatabaseSettings.array_block_size, "300" )
    .newGraphDatabase();

         为了确保数据库正确地关闭,可添加一个ShutdownHook来实现关闭数据库的动作。关闭数据库可以调用shutdown()方法

private static void registerShutdownHook(final GraphDatabaseService graphDb) {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                graphDb.shutdown();
            }
        });
}

    5. 创建节点和关系

        关系、Label类型可以通过枚举enum创建

// Label类型枚举类
private static enum MyLabels implements Label {
    MOVIES, USERS
}

//关系类型枚举类
private static enum MyRelationshipTypes implements RelationshipType {
    IS_FRIEND_OF, HAS_SEEN
}

    6. 在Neo4j中,对于数据库的操作需要在一个事务transaction中执行

try ( Transaction tx = graphDb.beginTx() ){
    // 数据库操作写在事务提交之前

    tx.success();
}

    7. 汇总上述并给出一个案例

import org.neo4j.graphdb.*;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;

import java.io.File;

public class Neo4jNativeJavaAPI {
    private static void registerShutdownHook(final GraphDatabaseService graphDB) {
        Runtime.getRuntime().addShutdownHook(
                new Thread() {
                    public void run() {
                        System.out.println("Server is shutting down");
                        graphDB.shutdown();
                    }
                }
        );
    }

    //Label类型枚举类
    private static enum MyLabels implements Label {
        MOVIES, USERS
    }

    //关系类型枚举类
    private static enum MyRelationshipTypes implements RelationshipType {
        IS_FRIEND_OF, HAS_SEEN
    }

    public static void main(String[] args) {
        //指定 Neo4j 存储路径,这里的test.db不需要提前创建
        File file = new File("/usr/local/neo4j/data/databases/test.db");
        //Create a new Object of Graph Database
        GraphDatabaseService graphDB = new GraphDatabaseFactory().newEmbeddedDatabase(file);
        System.out.println("Server is up and Running");

        try(Transaction tx = graphDB.beginTx()){
            //新增Actor节点 添加Label以区分节点类型 每个节点设置name属性
            Node user1 = graphDB.createNode(MyLabels.USERS);
            user1.setProperty("name", "John Johnson");

            Node user2 = graphDB.createNode(MyLabels.USERS);
            user2.setProperty("name", "Kate Smith");

            Node user3 = graphDB.createNode(MyLabels.USERS);
            user3.setProperty("name", "Jack Jeffries");

            /**
             * 为user1添加Friend关系
             * 注:Neo4j的关系是有向的箭头,正常来讲Friend关系应该是双向的,
             * 此处为了简单起见,将关系定义成单向的,不会影响后期的查询
             */
            user1.createRelationshipTo(user2,MyRelationshipTypes.IS_FRIEND_OF);
            user1.createRelationshipTo(user3,MyRelationshipTypes.IS_FRIEND_OF);

            /**
             * 新增Movie节点
             * 添加Lable以区分节点类型
             * 每个节点设置name属性
             */
            Node movie1 = graphDB.createNode(MyLabels.MOVIES);
            movie1.setProperty("name", "Fargo");

            Node movie2 = graphDB.createNode(MyLabels.MOVIES);
            movie2.setProperty("name", "Alien");

            Node movie3 = graphDB.createNode(MyLabels.MOVIES);
            movie3.setProperty("name", "Heat");

            /**
             * 为User节点和Movie节点之间添加HAS_SEEN关系, HAS_SEEN关系设置stars属性
             */
            Relationship relationship1 = user1.createRelationshipTo(movie1, MyRelationshipTypes.HAS_SEEN);
            relationship1.setProperty("stars", 5);
            Relationship relationship2 = user2.createRelationshipTo(movie3, MyRelationshipTypes.HAS_SEEN);
            relationship2.setProperty("stars", 3);
            Relationship relationship6 = user2.createRelationshipTo(movie2, MyRelationshipTypes.HAS_SEEN);
            relationship6.setProperty("stars", 6);
            Relationship relationship3 = user3.createRelationshipTo(movie1, MyRelationshipTypes.HAS_SEEN);
            relationship3.setProperty("stars", 4);
            Relationship relationship4 = user3.createRelationshipTo(movie2, MyRelationshipTypes.HAS_SEEN);
            relationship4.setProperty("stars", 5);

            tx.success();
            System.out.println("Done successfully");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            graphDB.shutdown();    //关闭数据库
        }

        //Register a Shutdown Hook
        registerShutdownHook(graphDB);
    }
}

        运行后却报错了:Error starting org.neo4j.graphdb.facade.GraphDatabaseFacadeFactory 

        在网上没有找到明确的解决办法,但找到类似的 [链接],说是因为已经成功初始化,但是在继续初始化启动就会报错,那很简单的解决方法就是把neo4j安装目录下的/data/databases里面的所有文件都删除掉(可以先备份再删掉),操作后再运行程序成功了

Neo4j:入门基础(四)之Java API_第5张图片

        由于neo4j默认启动的是graph.db数据库,而我们这里用了新的数据库test.db,所以到/conf/neo4j.conf修改配置 

        启动neo4j 

        浏览器打开http://localhost:7474 

Neo4j:入门基础(四)之Java API_第6张图片

 

    8.  再创建一个Java类Neo4jCypherJavaAPI,用 Cypher 对上图进行查询

import org.neo4j.graphdb.*;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;

import java.io.File;

public class Neo4jCypherJavaAPI {
    public static void main(String[] args) {
        //指定 Neo4j 存储路径
        File file = new File("/usr/local/neo4j/data/databases/test.db");
        //Create a new Object of Graph Database
        GraphDatabaseService graphDB = new GraphDatabaseFactory().newEmbeddedDatabase(file);
        System.out.println("Server is up and Running");

        try(Transaction tx = graphDB.beginTx()){
            //通过Cypher查询获得结果
            StringBuilder sb = new StringBuilder();
            sb.append("MATCH (john)-[:IS_FRIEND_OF]->(USER)-[:HAS_SEEN]->(movie) ");
            sb.append("RETURN movie");
            Result result = graphDB.execute(sb.toString());
            //遍历结果
            while(result.hasNext()){
                //get("movie")和查询语句的return movie相匹配
                Node movie = (Node) result.next().get("movie");
                System.out.println(movie.getId() + " : " + movie.getProperty("name"));
            }

            tx.success();
            System.out.println("Done successfully");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            graphDB.shutdown();    //关闭数据库
        }
    }
}

Neo4j:入门基础(四)之Java API_第7张图片

 

更多

     1. 上述代码主要实现的是创建(CREATE)节点和关系,也可以进行更新、查询、删除等

try (Transaction tx = graphDB.beginTx()) {
    // 查询节点
    Node node = graphDB.findNode(MyLabels.ACTORS, "name", "John Johnson");
    System.out.println("query node name is " + node.getProperty("name"));
    
    // 更新节点
    node.setProperty("birthday", "1979-01-18");
    System.out.println(node.getProperty("name") + "'s birthday is " + 
    node.getProperty("birthday", new String()));
    
    // 删除关系和节点
    Relationship relationship = node.getSingleRelationship(MyRelationshipTypes.IS_FRIEND_OF, Direction.OUTGOING);
    relationship.delete();
    relationship.getStartNode().delete();
    node.delete();
    
    // 提交事务
    tx.success();
}

 

    2. Neo4j可以以两种方式运行 [链接]:

      如今大多数数据库是作为服务器并通过客户端来访问的。Neo4j能够以嵌入式运行,也能以服务器模式运行——事实上,回顾到近十年前,它就是作为嵌入式图形数据库起源的。

     2.1 Java应用程序中的嵌入式数据库(如:本篇博文用的该方式

       嵌入式Neo4j数据库是性能的最佳选择。 它运行在相同的客户端应用程序的进程托管它并将数据存储在给定的路径中。

Neo4j:入门基础(四)之Java API_第8张图片

     2.2 通过REST的独立服务器(如:基于电影知识图谱的智能问答系统 用的该方式

       作为独立应用程序,它比嵌入式配置更安全(客户端中的潜在故障不会影响服务器),并且更易于监控。要连接到Neo4j服务器,必须使用REST API,可以使用Python,.NET,Java,Go,PHP,Ruby,Node.js等。使用服务器开发的方式,Neo4j必须是开启的状态

Neo4j:入门基础(四)之Java API_第9张图片

       通过独立服务器方式访问可以使用bolt或者http协议,bolt是neo4j官方开发的访问协议,性能较高 [来源]

       其他:neo4j jdbc连接数据库用http协议和bolt协议得到的数据不一样

       其他:Neo4j_嵌入模式&服务器模式区别

    在基于Web的应用程序中,HTTP方法对于区分对服务器端有很大副作用的写请求和对服务器端没有很大的副作用的那些请求(POST、PUT和DELETE会修改服务器端的资源,而GET请求对服务器端是无副作用的)已经足够了。

 

    3. ORM与JDBC的区别

        http://blog.itblood.com/3431.html

 

其他

Neo4j:入门基础(四)之Java API_第10张图片

Neo4j:入门基础(四)之Java API_第11张图片

 

系列

    Neo4j:入门基础(一)之安装与使用

    Neo4j:入门基础(二)之导入CSV文件

    Neo4j:入门基础(三)之APOC插件

    Neo4j:入门基础(四)之Java API

    Neo4j:入门基础(五)之SDN

    Neo4j:入门基础(六)之从MySQL导入数据

    Neo4j:入门基础(七)之Algo插件

    Neo4j:入门基础(八)之Traversal API

 

参考

    CSDN 修行修心:图数据库 Neo4j 之 Java Api 的使用

    博客园 没课割绿地:Neo4j学习笔记(1)——使用Java API实现简单的增删改查

    CSDN Karenmaxx:Springboot连接Neo4j 完整版(提供代码)

你可能感兴趣的:(知识图谱)