Neo4j+D3展现的应用实例

        之前已经写过一篇文章简要介绍了图数据库Neo4j的概念,没看过的读者可以在此点链接《图数据库Neo4j简介》。本文主要讲解图数据库在真实项目中的实践应用,取自于我参与的真实项目代码。

        后端用的是图数据库Neo4j来存节点和关系,前端用的是D3来画图。前后端交互是通过json数据来完成的,即Neo4j查出的结果组装成json后,传递给D3来画图。


1 Neo4j

        首先看一下pom文件相关代码,如下:

<dependency>
    <groupId>org.neo4j.driver</groupId>
    <artifactId>neo4j-java-driver</artifactId>
    <version>1.5.0</version>
</dependency>

        如图所示,我用的是neo4j-java-driver连接的Neo4j,当然也可以选择其他方式。例如Spring-Data-Neo4j等连接方式(只不过我所在项目中的spring版本和Spring-Data-Neo4j版本冲突,所以不能使用)。

        然后是加载驱动的代码如下:

private static void driverConnect() {
    InputStream in = GraphDriverManager.class.getClassLoader().getResourceAsStream(LOCAL);
    Properties p = new Properties();
    try {
        p.load(in);
    } catch (IOException e) {
        e.printStackTrace();
    }
    String url = p.getProperty("neo4j.url");
    String userName = p.getProperty("neo4j.username");
    String passWord = p.getProperty("neo4j.password");
    // 使用 basic authentication方式创建连接
    try {
        driver = GraphDatabase.driver(url, AuthTokens.basic(userName, passWord), Config.build().withMaxConnectionLifetime(30, TimeUnit.MINUTES).withMaxConnectionPoolSize(50).withConnectionAcquisitionTimeout(2, TimeUnit.MINUTES).toConfig());
        resetFlag();
    } catch (Exception e) {
        logger.error("图数据库连接异常",e);
        //当数据库连接异常时,把标志位写进文件,做提示用。
        ErrorConnectPut();
    }
}

        java连接Neo4j的方式有三种:bolt、http和https,我选用的是bolt协议。同时为了方便,将Neo4j的url、用户名和密码做成properties文件来读取。

        最后就是具体的调用代码了。如下所示:

@Override
public Map<Set<String>, Set<String>> searchAllPathsOfTwoNodes(String firstLabel, String firstName, String secondLabel, String secondName) {
    Map<Set<String>, Set<String>> searchResults = null;
    Driver driver = driverManager.getDriver();
    try (Session session = driver.session()) {
        searchResults = session.readTransaction(tx -> {
            return standardGraphDao.searchAllPathsOfTwoNodes(tx, firstLabel, firstName, secondLabel, secondName);
        });
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return searchResults;
}

        用内部类和lambda表达式的方式调用DAO层的代码。正如在之前文章中所提,应避免写出循环开闭事务的代码,应将循环放进DAO层里。

        但是该种写法只是示例写法,用在实际的项目中会有很大的效率问题。假如在该方法中还需要调用test方法,那么不可避免的是test方法中仍然需要获取事务,这就会有嵌套事务的情况出现,在一些方法比较复杂和大数据量的执行下,效率会直线下降。解决办法是统一使用写事务(用写事务来代替读事务用以实现统一的事务获取,目前我还没有发现相关的bug),只有在最外面的方法才获取事务,里面如果有方法调用,则将事务tx一同作为参数传递过去,这样在整个方法中只有一次获取事务的情况出现。

        但这样虽然解决了效率问题,在整个service层的开发却变得异常糟糕:充斥着大量的try...catch...业务无关语句。很自然的想到,可以用AOP进行改造,改造结果如下:

@Around("pointCut()")
public Object around(ProceedingJoinPoint jp) {
    MethodSignature msig = (MethodSignature) jp.getSignature();
    Method method = msig.getMethod();
    Object returnType = method.getReturnType();
    try {
        Field txField = StandardGraphDao.class.getDeclaredField("tx");
        txField.setAccessible(true);
        Driver driver = driverManager.getDriver();
        try (Session session = driver.session()) {
            returnType = session.writeTransaction(tx -> {
                try {
                    txField.set(StandardGraphDao.class.newInstance(), tx);
                    return jp.pr
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值