配置

驱动程序类名

Neo4j JDBC 驱动程序是 org.neo4j.jdbc.Neo4jDriver。使用现代 Java 工具时,您通常不需要直接操作此类的,但有些连接池和前端会要求您提供此信息。该类是公共 API。

我们还提供 org.neo4j.jdbc.Neo4jDataSource 作为 javax.sql.DataSource

因果集群和书签

Neo4j JDBC 驱动程序默认使用书签来提供所有 Neo4j 部署中的因果一致性。书签在驱动程序级别本身进行管理,而不是在由驱动程序实例生成的连接上进行管理,因此一个实例生成的所有连接都将参与相同的因果事务链。来自不同驱动程序实例的连接将不会使用相同的书签集,并且没有内置机制可以实现这一点。如果您需要此功能,可以直接访问 Neo4jDriver 类型以检索当前已知书签集并将其传递给另一个驱动程序实例。

Neo4j 事务元数据

Neo4j 支持将元数据附加到事务,参见 SHOW TRANSACTIONS。由于 JDBC 规范中没有明确的事务对象,Neo4j JDBC 驱动程序需要另一种机制来使其可配置。

JDBC 驱动程序提供了扩展接口 Neo4jMetadataWriter。我们的驱动程序、连接实现和所有语句变体都可以相应地解包。配置是累加的:为驱动程序实例配置的元数据将用于从该驱动程序生成的所有连接,连接可以添加更多元数据,语句也可以添加自己的元数据。在语句上添加的元数据优先于连接元数据,连接元数据又优先于驱动程序元数据。

列表 1. 配置事务元数据
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.neo4j.jdbc.Neo4jDriver;
import org.neo4j.jdbc.Neo4jMetadataWriter;

public final class TransactionMetadata {

    private static final Logger LOGGER = Logger.getLogger(TransactionMetadata.class.getPackageName());

    public static void main(String... args) throws SQLException {
        var url = "jdbc:neo4j://localhost:7687";

        var driver = (Neo4jDriver) DriverManager.getDriver(url);
        driver.withMetadata(Map.of("md_from_driver", "v1", "will_be_overwritten", "irrelevant"));

        var properties = new Properties();
        properties.put("user", "neo4j");
        properties.put("password", "verysecret");

        try (
            var con = driver.connect(url, properties)
                .unwrap(Neo4jMetadataWriter.class)
                .withMetadata(Map.of("md_from_connection", "v2", "will_be_overwritten", "xxx"))
                .unwrap(Connection.class);
            var statement = con.createStatement()
                .unwrap(Neo4jMetadataWriter.class)
                .withMetadata(Map.of("md_from_stmt", "v3", "will_be_overwritten", "v4"))
                .unwrap(Statement.class)
        ) {
            try (var result = statement.executeQuery("SHOW TRANSACTIONS YIELD metaData")) {
                while (result.next()) {
                    var metaData = result.getObject("metaData", Map.class);
                    LOGGER.log(Level.INFO, "{0}", metaData);
                }
            }
        }
    }
}

输出将类似于此

Juli 17, 2024 1:18:16 PM org.neo4j.jdbc.docs.TransactionMetadata main
INFORMATION: {md_from_driver=v1, md_from_connection=v2, md_from_stmt=v3, will_be_overwritten=v4}

URL 和连接属性

Neo4j JDBC 驱动程序的标准 URL 格式是

jdbc:neo4j://<host>:<port>/<database>?param1=value1&param2=value2

数据库名称和所有查询参数都是可选的,可以省略。所有配置参数都可以作为查询参数或通过 java.util.Properties 对象传递。后者有时由工具为您定义。

关于身份验证,我们建议遵循 JDBC 规范,该规范不鼓励使用任何形式的 URL 身份验证。所有查询参数如果包含特殊字符,必须进行 百分比编码,例如 …​?param1=space%20separated

驱动程序支持以下 URI 方案,这些方案可调整安全配置

  • neo4j - 无加密。

  • neo4j+s - 启用加密,并且只接受由已知证书颁发机构签名的服务器 SSL 证书。

  • neo4j+ssc - 启用加密并接受自签名证书(必须将其添加到证书存储中)。

不支持 bolt URI 方案。

驱动程序接受以下配置参数,可以作为属性或 URL 查询参数

表 1. 配置参数
名称 类型 含义 默认值

timeout

Integer

连接获取超时时间(毫秒)

1000

agent

String

用户代理

neo4j-jdbc

enableSQLTranslation

Boolean

启用 SQL 到 Cypher 自动转换的标志(要求类路径上有转换器)

false

cacheSQLTranslations

Boolean

启用转换缓存的标志。SQL 转换并非“免费”:解析 SQL 需要花费一些时间,Cypher® 渲染也是如此。此外,我们可能还需要查找元数据以投射各个属性。如果耗时过长,转换可能会被缓存。

false

rewritePlaceholders

Boolean

允许您在 Cypher 语句中使用 ? 作为占位符(JDBC 要求)的标志。这些占位符将自动重写为 $1$2$n,从 1 开始编号,以匹配基于 1 的 JDBC 索引。

enableSQLTranslationfalse 时为 true,否则为 false

ssl

Boolean

可选标志,是 neo4j+s 的替代方案。例如,它可以用于以编程方式启用完整的 SSL 链。

null

sslMode

Enum<SSLMode>

用于精细控制 SSL 配置的可选配置。允许的值为 disablerequireverify-full。参见 <ssl_mode, 理解 SSL 模式>>。

null

user

String

用于身份验证的用户名(主体)。出于安全原因,不建议作为 URL 查询参数使用。

neo4j

password

String

用于身份验证的密码(凭据)。出于安全原因,不建议作为 URL 查询参数使用。

password

authRealm

String

用于身份验证的领域。出于安全原因,不建议作为 URL 查询参数使用。

null

authScheme

String

要使用的身份验证方案。出于安全原因,不建议作为 URL 查询参数使用。当前支持的值有

  • basic(默认)用于基本身份验证。

  • bearer 用于持有者身份验证(SSO)。password 应设置为持有者令牌;userauthRealm 无效。

  • kerberos 用于 Kerberos 身份验证。要求 password 设置为 Kerberos 票据;userauthRealm 无效。

  • 如果服务器上禁用了身份验证,则为 none。属性 userpasswordauthRealm 无效。

basic

useBookmarks

boolean

启用书签管理以全面支持因果集群。此功能默认启用,并且是所有使用连接池的场景的推荐设置。如果您禁用它,它将仅对特定连接禁用。从驱动程序实例获取到相同或其他数据库的其他连接不受影响,并且各个连接仍将管理其书签。

true

viewDefinitions

String

指向有效 JSON 文件(包含 Cypher 支持的视图 定义)的文件、http 或 https URL。

null

获取驱动程序或连接实例

本节可能仅适用于您将 Neo4j JDBC 驱动程序作为应用程序开发的一部分使用,而不是作为 DBeaver、DataGrip 或基于 UI 的 ETL 工具等前端工具的一部分使用。

获取连接最简单的方法是直接通过 java.sql.DriverManager

列表 2. 获取到 Neo4j 服务器的 JDBC 连接
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

class Configuration {

    void obtainConnection() throws SQLException {

        var url = "jdbc:neo4j://localhost:7687";
        var username = "neo4j";
        var password = "verysecret";
        var connection = DriverManager.getConnection(url, username, password);
    }

}

尽管我们的连接实现是线程安全的,但它(根据 JDBC 规范)每个连接只允许一个并发事务。对于多线程应用程序,请使用连接池。有 HikariCP,但通常应用程序服务器和容器/框架会自带连接池。使用其中任何一个都是安全的,因为 Neo4j JDBC 驱动程序不进行内部池化。

如果您需要访问 Neo4j 驱动程序本身的实例,可以使用以下方法

列表 3. 获取 Neo4j JDBC 驱动程序实例
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

class Configuration {

    void obtainDriverAndConnection() throws SQLException {

        var url = "jdbc:neo4j://localhost:7687";
        var driver = DriverManager.getDriver(url);

        var properties = new Properties();
        properties.put("username", "neo4j");
        properties.put("password", "verysecret");
        var connection = driver.connect(url, properties);
    }

}

使用 SSL 保护连接

Neo4j JDBC 驱动程序支持与通用 Java 驱动程序相同的 SSL 选项,使用相同的 URL 协议,并使用 +s+ssc 作为所需安全级别的额外指示符。

相同的配置也可以通过 URL 查询参数或在请求连接时传递给 DriverManager 或驱动程序实例的属性中的条目来实现。只要您不指定相互矛盾的值,结合这两种方法是可行的。

理解 SSL 模式

以下列表按安全级别升序排列

  • disable — (默认),“我不在乎安全性,也不想为加密支付额外开销。”

  • require — “我希望我的数据被加密,并且我接受开销。我信任网络会确保我始终连接到我想要的服务器。”(服务器必须支持加密,不进行主机名/CA 验证。这省去了正确证书的麻烦,并且只在私有网络上安全;不应在公共网络上使用。)

  • verify-full — “我希望我的数据被加密,并且我接受开销。我希望确保我连接到我信任的服务器,并且是我指定的服务器。”

Neo4j JDBC 驱动程序不包含撤销检查。

最安全的选项也可以通过将 ssl=true 设置为查询参数或作为传递给 DriverManager 的属性条目来启用。此选项对应于 neo4j+s。另一方面,require 对应于 neo4j+ssc

额外的枚举允许我们未来可能支持更多模式,例如让服务决定 SSL,或能够表达对 SSL 的偏好而不强制要求。

Neo4j 服务器可以提供纯 Bolt 连接和加密 SSL 连接,或仅提供其中一种。您可以使用 neo4j+s 连接并不意味着您不能仅使用 neo4j 连接,反之亦然。这取决于服务器设置。Neo4j Aura,Neo4j 的托管云服务,仅支持加密连接,因此您必须使用 +sssl=truesslMode=verify-full

有效 URL

以下 URL 均有效

neo4j+s://xyz.databases.neo4j.io

对 AuraDB 上的 xzy 实例使用完全验证

neo4j://xyz.databases.neo4j.io?ssl=true

相同,但使用简写 URL 参数

neo4j://xyz.databases.neo4j.io?sslMode=verfiy-full

相同,但使用显式模式

neo4j+s://xyz.databases.neo4j.io?ssl=true&sslMode=verify-full

并非更安全,但不会对您造成失败

neo4j+ssc://this.is.a.trustworthy.instance.for.sure.com

信任所有证书和主机名,但务必使用 SSL

neo4j://my-testing-instance.local

使用普通连接。

驱动程序只会拒绝相互矛盾的配置,例如

  • +sssl=false,或 sslMode 设置为 disable

  • +sscssl=false,或任何不等于 requiresslmode

基本上,您不能同时要求使用 SSL 又不使用它。驱动程序提供了多种机制,以便您可以以编程方式使用具有动态查询参数的固定 URL,或动态 URL,或您偏好的任何配置方式。

使用 .dotenv 文件

当您创建一个 Neo4j Aura 实例时,系统会要求您下载一个类似于 Neo4j-9df57663-Created-2023-06-12.txt 的文本文件。这本质上是一个 .dotenv 文件,其中包含连接到数据库所需的信息。

这些文件可以通过 Neo4jDriver.fromEnv() 直接使用(参见 通过环境变量获取连接)。此方法有多个重载,允许您配置文件名和目录。此外,构建器还允许您配置 Aura 文件中不包含的选项。

日志记录

通过标准 Java 设置

要生成有用且详细的日志,您必须配置 java.util.logging。这可以通过配置文件或编程方式完成。以下部分包含一个示例配置,将全局日志级别设置为 INFO,Neo4j JDBC 驱动程序本身设置为 DEBUG,所有网络相关内容设置为 WARN

列表 4. 记录所有信息的 Neo4j JDBC 驱动程序日志配置
.level = INFO
handlers=java.util.logging.ConsoleHandler

# The handler must be configured for the lowest level it should catch
java.util.logging.ConsoleHandler.level=FINEST

# Enables all Logging for the JDBC Driver
org.neo4j.jdbc.level=ALL
# But reduces the noise on the network and the result set
org.neo4j.jdbc.result-set.level=WARNING
org.neo4j.jdbc.network.level=WARNING
# This is an example how to configure the outbound and inbound messages
org.neo4j.jdbc.network.OutboundMessageHandler.level=FINE
org.neo4j.jdbc.network.InboundMessageHandler.level=FINE

# This produces a date, followed by the level, 3 dashes, the message and the source of the log if available
java.util.logging.SimpleFormatter.format = %1$tFT%1$tk:%1$tM:%1$tS.%1$tL%1$tz %4$-15s --- %5$s [%2$s]%n

此类文件必须作为系统属性通过以下方式传递给正在运行的 Java 程序

java -Djava.util.logging.config.file=docs/src/main/resources/logging-to-console.properties <your program>

将日志捕获到文件需要更改处理程序

列表 5. 将所有 JDBC 日志写入文件的 Neo4j JDBC 驱动程序日志配置
.level = INFO
handlers=java.util.logging.ConsoleHandler

# Keep everything by default at INFO
java.util.logging.ConsoleHandler.level=INFO

# The handler must be configured for the lowest level it should catch
java.util.logging.FileHandler.level=FINEST
java.util.logging.FileHandler.pattern=jdbc.log
# XML Format by default
# java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter

# Change the handler for JDBC
org.neo4j.jdbc.handlers=java.util.logging.FileHandler
# Keep the rest as above
org.neo4j.jdbc.level=ALL
org.neo4j.jdbc.result-set.level=WARNING
org.neo4j.jdbc.network.level=WARNING
org.neo4j.jdbc.network.OutboundMessageHandler.level=FINE
org.neo4j.jdbc.network.InboundMessageHandler.level=FINE

java.util.logging.SimpleFormatter.format = %1$tFT%1$tk:%1$tM:%1$tS.%1$tL%1$tz %4$-15s --- %5$s [%2$s]%n
JDBC 驱动程序的诊断功能基于标准的 java.util.logging 框架。该框架本身的配置超出本文档的范围。如需完整概述,您可能需要从 “Java 日志概述” 开始。Java 使用的格式化程序是 java.util.Formatter

在 Spring Boot 应用程序中

Neo4j JDBC 驱动程序将集成到 Spring Boot 日志配置中,并从中获取所有相关的格式和其他设置。日志级别可以使用 Spring 理解的级别进行配置。以下配置与上述配置等效

列表 6. Spring Boot 配置文件中 Neo4j JDBC 驱动程序的日志配置
logging.level.org.neo4j.jdbc=trace
logging.level.org.neo4j.jdbc.result-set=warn
logging.level.org.neo4j.jdbc.network=warn
logging.level.org.neo4j.jdbc.network.OutboundMessageHandler=debug
logging.level.org.neo4j.jdbc.network.InboundMessageHandler=debug

在 Quarkus 应用程序中

Neo4j JDBC 驱动程序将集成到 Quarkus 日志配置中,并从中获取所有相关的格式和其他设置。日志级别可以使用 Quarkus 理解的级别进行配置。以下配置与上述配置等效

列表 7. Quarkus 配置文件中 Neo4j JDBC 驱动程序的日志配置
quarkus.log.category."org.neo4j.jdbc".min-level=TRACE
quarkus.log.category."org.neo4j.jdbc".level=TRACE
quarkus.log.category."org.neo4j.jdbc.result-set".level=DEBUG
quarkus.log.category."org.neo4j.jdbc.network".level=WARNING
quarkus.log.category."org.neo4j.jdbc.network.OutboundMessageHandler".level=DEBUG
quarkus.log.category."org.neo4j.jdbc.network.InboundMessageHandler".level=DEBUG

SQL 转换

SQL 转换器使用日志记录器 org.neo4j.jdbc.translator;处理过的 SQL 及其原始源以 FINE 级别记录在 org.neo4j.jdbc.statement.SQL 上。

指标

Neo4j JDBC 驱动程序将通过 Micrometer 发布指标。如果您将 Micrometer 放在类路径上,则无需进一步配置。例如,Spring Boot ActuatorMicrometer for Quarkus 会自动实现这一点。为了充分利用此功能,您还需要配置您的 监控系统

Neo4j JDBC 驱动程序发布以下指标

org.neo4j.jdbc.connections

一个表示打开连接数的计量器,标记有驱动程序连接到的 url

org.neo4j.jdbc.statements

一个表示打开语句数的计量器,标记有语句打开到的 url 和语句的 JDBC 类型(StatementPreparedStatementCallableStatement

org.neo4j.jdbc.queries

一个复合计量器,包含成功和失败查询的计数以及一个测量查询持续时间的计时器

org.neo4j.jdbc.cached-translations

一个表示已缓存的 SQL 到 Cypher 转换数量的计量器

跟踪

Neo4j JDBC 驱动程序支持跟踪,并将为 JDBC Statement 实例上的以下操作提供跟踪跨度

  • #execute

  • #executeQuery

  • #executeUpdate

及其所有重载和所有继承类型。此外,当使用 JDBC ResultSet 时,它会在结果集首次从第一行之前移动到移到最后一行之外或主动关闭时打开一个跨度。跨度将包含各种事件,例如查询实际由 Neo4j 数据库执行时,或从数据库中拉取一批记录时。

该功能是可选的:当您想要使用它时,必须引入额外的依赖项。这适用于所有分布式版本,包括完整捆绑包,这样可选功能就不会使捆绑包更大。对于 Maven,使用此附加依赖项声明

列表 8. 允许您配置跟踪的 Maven 依赖项
<dependency>
    <groupId>org.neo4j</groupId>
    <artifactId>neo4j-jdbc-tracing-micrometer</artifactId>
    <version>6.5.1</version>
</dependency>

对于 Gradle,您需要声明以下运行时依赖项

列表 9. 允许您配置跟踪的 Gradle 依赖项
dependencies {
    runtimeOnly 'org.neo4j:neo4j-jdbc-tracing-micrometer:6.5.1'
}

此依赖项引入了 Micrometer Tracing。Micrometer Tracing 允许您绑定到各种跟踪器和导出器,例如 Zipkin 或 OpenTelemetry。

获得 Micrometer Tracer 后,您可以像这样配置 Neo4jDataSource

列表 10. 一个 Neo4jDataSource 生成跟踪其使用情况的连接
import javax.sql.DataSource;

import org.neo4j.jdbc.Neo4jDataSource;
import org.neo4j.jdbc.tracing.micrometer.Neo4jTracingBridge;

import io.micrometer.tracing.Tracer;

public class TracingExampleSetup {

    DataSource neo4jDataSource() {

        Tracer tracer = Tracer.NOOP; (1)
        var neo4jDataSource = new Neo4jDataSource();
        neo4jDataSource.setUrl("jdbc:neo4j://yourhost:7687");
        neo4jDataSource.setPassword("neo4j");
        neo4jDataSource.setUser("verysecret");
        neo4jDataSource.setTracer(Neo4jTracingBridge.to(tracer)); (2)
        return neo4jDataSource;
    }
}
1 在大多数情况下,您的应用程序框架将为您提供一个 Micrometer 跟踪器实例
2 通过此调用,您可以在数据源及其生成的所有连接中启用跟踪

您还可以通过将单个连接解包到 Neo4jConnection 扩展中来启用跟踪,如下所示

列表 11. 为单个连接启用跟踪
import java.sql.Connection;
import java.sql.DriverManager;

import org.neo4j.jdbc.Neo4jConnection;
import org.neo4j.jdbc.tracing.micrometer.Neo4jTracingBridge;

import io.micrometer.tracing.Tracer;

public class TracingExampleSetup {

    Connection connection() {

        Tracer tracer = Tracer.NOOP;
        return DriverManager.getConnection("jdbc:neo4j://yourhost:7687", "neo4j", "verysecret")
            .unwrap(Neo4jConnection.class) (1)
            .withTracer(Neo4jTracingBridge.to(tracer));
    }
}
1 将连接解包到我们的扩展中,以便您可以配置跟踪器。

在 Spring Boot 中使用跟踪

Neo4j JDBC 驱动程序提供的跟踪实现利用了 Micrometer Tracing,它在 Spring Boot 生态系统以及 Quarkus、Micronaut 等框架中广受欢迎。我们提供了一些示例,但请参阅您的框架文档以了解如何配置跟踪。

配置跟踪数据源

通常,Spring Boot 会根据您的驱动程序配置 HikariDataSource。Hikari 提供了连接池,您不应该放弃它。无需为您所有的配置值创建自己的数据源属性,您可以像这样注入它

列表 12. 使用 Spring Boot 配置跟踪和池化数据源
import javax.sql.DataSource;

import org.neo4j.jdbc.Neo4jDataSource;
import org.neo4j.jdbc.tracing.micrometer.Neo4jTracingBridge;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import io.micrometer.tracing.Tracer;

@Configuration
class TracingTestConfiguration {

    @Bean
    DataSource neo4jDataSource(Tracer tracer, DataSourceProperties dataSourceProperties) {

        var neo4jDataSource = new Neo4jDataSource();
        neo4jDataSource.setUrl(dataSourceProperties.getUrl());
        neo4jDataSource.setPassword(dataSourceProperties.getPassword());
        neo4jDataSource.setUser(dataSourceProperties.getUsername());
        neo4jDataSource.setTracer(Neo4jTracingBridge.to(tracer));

        var cfg = new HikariConfig();
        cfg.setDataSource(neo4jDataSource);
        return new HikariDataSource(cfg);
    }
}

同时将 org.springframework.boot:spring-boot-starter-actuator 添加到您的类路径中,它将为您配置 Micrometer。

您的数据源设置保持不变:以下示例无需更改即可正常工作,因为我们的跟踪 API 将通过 Micrometer 自动选择正确的跟踪器!

导出到 Zipkin

要将跟踪导出到 Zipkin,请添加 io.micrometer:micrometer-tracing-bridge-braveio.zipkin.reporter2:zipkin-reporter-brave,并在 Spring 应用程序中将 management.zipkin.tracing.export.enabled 设置为 true

您应该会看到如下跨度

zipkintracing

通过 OpenTelemetry 导出

OpenTelemetry 不仅可以导出跟踪,还可以导出指标和日志。

以下是通过 OpenTelemetry 使用 Dash0 的示例。导出器对于其他服务也应该同样有效。OpenTelemetry 已将其 SDK 拆分为多个模块,因此您首先需要将其 BOM 导入到您的构建文件中。以下是 Maven 的示例

列表 13. 包含 OpenTelemetry BOM 的 Maven 构建文件片段
<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-bom</artifactId>
    <version>1.47.0</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

首先,您需要通过 io.micrometer:micrometer-tracing-bridge-otel 引入从 Micrometer 到 OpenTelemetry 的桥接,以便 Micrometer 推送数据到该 SDK。接下来,引入以下依赖项,以便 Spring Boot 可以配置导出器

  • io.opentelemetry:opentelemetry-sdk

  • io.opentelemetry:opentelemetry-exporter-common

  • io.opentelemetry:opentelemetry-exporter-otlp

  • io.opentelemetry:opentelemetry-exporter-sender-jdk

对于 Dash0,应用程序配置将类似于此

列表 14. 在 Spring Boot 中使用 OpenTelemetry 导出器到 Dash0
management.otlp.tracing.export.enabled=true
management.otlp.tracing.endpoint=https://ingress.eu-west-1.aws.dash0.com/v1/traces
management.otlp.tracing.headers.Authorization=Bearer auth_XX_your_token_XX

management.otlp.metrics.export.step=30s
management.otlp.metrics.export.enabled=true
management.otlp.metrics.export.url=https://ingress.eu-west-1.aws.dash0.com/v1/metrics
management.otlp.metrics.export.headers.Authorization=Bearer auth_XX_your_token_XX

我们的电影应用程序的跟踪如下所示

dash0tracing