

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Neptune openCypher 中的事务
<a name="access-graph-opencypher-transactions"></a>

Amazon Neptune 中的 openCypher 实现使用 [Neptune 定义的事务语义](transactions-neptune.md)。但是，如以下各节所述，Bolt 驱动程序提供的隔离级别对 Bolt 事务语义有一些特定的影响。

## 只读 Bolt 事务查询
<a name="access-graph-opencypher-transactions-ro"></a>

可以处理只读查询的方式多种多样，并可使用不同的事务模型和隔离级别，如下所示：

### 隐式只读事务查询
<a name="access-graph-opencypher-transactions-ro-implicit"></a>

以下是只读隐式事务的示例：

```
public void executeReadImplicitTransaction()
{
  // end point
  final String END_POINT = "(End Point URL)";

  // read query
  final String READ_QUERY = "MATCH (n) RETURN n limit 10";

  // create the driver
  final Driver driver = GraphDatabase.driver(END_POINT, AuthTokens.none(),
          Config.builder().withEncryption()
                          .withTrustStrategy(TrustStrategy.trustSystemCertificates())
                          .build());

  // create the session config
  SessionConfig sessionConfig = SessionConfig.builder()
                                             .withFetchSize(1000)
                                             .withDefaultAccessMode(AccessMode.READ)
                                             .build();

  // run the query as access mode read
  driver.session(sessionConfig).readTransaction(new TransactionWork<String>()
    {
      final StringBuilder resultCollector = new StringBuilder();

      @Override
      public String execute(final Transaction tx)
      {
        // execute the query
        Result queryResult = tx.run(READ_QUERY);

        // Read the result
        for (Record record : queryResult.list())
        {
          for (String key : record.keys())
          {
            resultCollector.append(key)
                           .append(":")
                           .append(record.get(key).asNode().toString());
          }
        }
        return resultCollector.toString();
      }

    }
  );

  // close the driver.
  driver.close();
}
```

由于只读副本仅接受只读查询，因此，无论在会话配置中设置的访问模式如何，所有针对只读副本的查询都将作为读取隐式事务执行。Neptune 在 `SNAPSHOT` 隔离语义下将读取隐式事务计算为[只读查询](transactions-neptune.md#transactions-neptune-read-only)。

如果失败，默认情况下会重试读取隐式事务。

### 自动提交只读事务查询
<a name="access-graph-opencypher-transactions-ro-autocommit"></a>

以下是只读自动提交事务的示例：

```
public void executeAutoCommitTransaction()
{
  // end point
  final String END_POINT = "(End Point URL)";

  // read query
  final String READ_QUERY = "MATCH (n) RETURN n limit 10";

  // Create the session config.
  final SessionConfig sessionConfig = SessionConfig
    .builder()
    .withFetchSize(1000)
    .withDefaultAccessMode(AccessMode.READ)
    .build();

  // create the driver
  final Driver driver = GraphDatabase.driver(END_POINT, AuthTokens.none(),
    Config.builder()
          .withEncryption()
          .withTrustStrategy(TrustStrategy.trustSystemCertificates())
          .build());

  // result collector
  final StringBuilder resultCollector = new StringBuilder();

  // create a session
  final Session session = driver.session(sessionConfig);

  // run the query
  final Result queryResult = session.run(READ_QUERY);
  for (final Record record : queryResult.list())
  {
    for (String key : record.keys())
    {
      resultCollector.append(key)
                     .append(":")
                     .append(record.get(key).asNode().toString());
    }
  }

  // close the session
  session.close();

  // close the driver
  driver.close();
}
```

如果在会话配置中将访问模式设置为 `READ`，则 Neptune 会在 `SNAPSHOT` 隔离语义下将自动提交事务查询计算为[只读查询](transactions-neptune.md#transactions-neptune-read-only)。请注意，只读副本仅接受只读查询。

如果您未传入会话配置，则默认情况下会使用突变查询隔离来处理自动提交查询，因此传入将访问模式显式设置为 `READ` 的会话配置非常重要。

如果失败，则不会重试只读自动提交查询。

### 显式只读事务查询
<a name="access-graph-opencypher-transactions-ro-explicit"></a>

以下是显式只读事务的示例：

```
public void executeReadExplicitTransaction()
{
  // end point
  final String END_POINT = "(End Point URL)";

  // read query
  final String READ_QUERY = "MATCH (n) RETURN n limit 10";

  // Create the session config.
  final SessionConfig sessionConfig = SessionConfig
    .builder()
    .withFetchSize(1000)
    .withDefaultAccessMode(AccessMode.READ)
    .build();

  // create the driver
  final Driver driver = GraphDatabase.driver(END_POINT, AuthTokens.none(),
    Config.builder()
          .withEncryption()
          .withTrustStrategy(TrustStrategy.trustSystemCertificates())
          .build());

  // result collector
  final StringBuilder resultCollector = new StringBuilder();

  // create a session
  final Session session = driver.session(sessionConfig);

  // begin transaction
  final Transaction tx = session.beginTransaction();

  // run the query on transaction
  final List<Record> list = tx.run(READ_QUERY).list();

  // read the result
  for (final Record record : list)
  {
    for (String key : record.keys())
    {
      resultCollector
        .append(key)
        .append(":")
        .append(record.get(key).asNode().toString());
    }
  }

  // commit the transaction and for rollback we can use beginTransaction.rollback();
  tx.commit();

  // close the driver
  driver.close();
}
```

如果在会话配置中将访问模式设置为 `READ`，则 Neptune 会在 `SNAPSHOT` 隔离语义下将显式只读事务计算为[只读查询](transactions-neptune.md#transactions-neptune-read-only)。请注意，只读副本仅接受只读查询。

如果您未传入会话配置，则默认情况下会使用突变查询隔离来处理显式只读事务，因此传入将访问模式显式设置为 `READ` 的会话配置非常重要。

如果失败，默认情况下会重试只读显式查询。

## 突变 Bolt 事务查询
<a name="access-graph-opencypher-transactions-wr"></a>

与只读查询一样，可以通过多种方式处理突变查询，并可使用不同的事务模型和隔离级别，如下所示：

### 隐式突变事务查询
<a name="access-graph-opencypher-transactions-wr-implicit"></a>

以下是隐式突变事务的示例：

```
public void executeWriteImplicitTransaction()
{
  // end point
  final String END_POINT = "(End Point URL)";

  // create node with label as label and properties.
  final String WRITE_QUERY = "CREATE (n:label {name : 'foo'})";

  // Read the vertex created with label as label.
  final String READ_QUERY = "MATCH (n:label) RETURN n";

  // create the driver
  final Driver driver = GraphDatabase.driver(END_POINT, AuthTokens.none(),
    Config.builder()
          .withEncryption()
          .withTrustStrategy(TrustStrategy.trustSystemCertificates())
          .build());

  // create the session config
  SessionConfig sessionConfig = SessionConfig
    .builder()
    .withFetchSize(1000)
    .withDefaultAccessMode(AccessMode.WRITE)
    .build();

  final StringBuilder resultCollector = new StringBuilder();

  // run the query as access mode write
  driver.session(sessionConfig).writeTransaction(new TransactionWork<String>()
  {
    @Override
    public String execute(final Transaction tx)
    {
      // execute the write query and consume the result.
      tx.run(WRITE_QUERY).consume();

      // read the vertex written in the same transaction
      final List<Record> list = tx.run(READ_QUERY).list();

      // read the result
      for (final Record record : list)
      {
        for (String key : record.keys())
        {
          resultCollector
            .append(key)
            .append(":")
            .append(record.get(key).asNode().toString());
        }
      }
      return resultCollector.toString();
    }
  }); // at the end, the transaction is automatically committed.

  // close the driver.
  driver.close();
}
```

作为突变查询一部分进行的读取是在 `READ COMMITTED` 隔离下执行的，对 [Neptune 突变事务](transactions-neptune.md#transactions-neptune-mutation)具有通常的保证。

无论您是否专门传入会话配置，该事务始终被视为写入事务。

有关冲突，请参阅[使用锁定等待超时解决冲突](transactions-neptune.md#transactions-neptune-conflicts)。

### 自动提交突变事务查询
<a name="access-graph-opencypher-transactions-wr-autocommit"></a>

突变自动提交查询继承与突变隐式事务相同的行为。

如果未传入会话配置，默认情况下，该事务将被视为写入事务。

如果失败，则不会自动重试突变自动提交查询。

### 显式突变事务查询
<a name="access-graph-opencypher-transactions-wr-explicit"></a>

以下是显式突变事务的示例：

```
public void executeWriteExplicitTransaction()
{
  // end point
  final String END_POINT = "(End Point URL)";

  // create node with label as label and properties.
  final String WRITE_QUERY = "CREATE (n:label {name : 'foo'})";

  // Read the vertex created with label as label.
  final String READ_QUERY = "MATCH (n:label) RETURN n";

  // create the driver
  final Driver driver = GraphDatabase.driver(END_POINT, AuthTokens.none(),
    Config.builder()
          .withEncryption()
          .withTrustStrategy(TrustStrategy.trustSystemCertificates())
          .build());

  // create the session config
  SessionConfig sessionConfig = SessionConfig
    .builder()
    .withFetchSize(1000)
    .withDefaultAccessMode(AccessMode.WRITE)
    .build();

  final StringBuilder resultCollector = new StringBuilder();

  final Session session = driver.session(sessionConfig);

  // run the query as access mode write
  final Transaction tx = driver.session(sessionConfig).beginTransaction();

  // execute the write query and consume the result.
  tx.run(WRITE_QUERY).consume();

  // read the result from the previous write query in a same transaction.
  final List<Record> list = tx.run(READ_QUERY).list();

  // read the result
  for (final Record record : list)
  {
    for (String key : record.keys())
    {
      resultCollector
        .append(key)
        .append(":")
        .append(record.get(key).asNode().toString());
    }
  }

  // commit the transaction and for rollback we can use tx.rollback();
  tx.commit();

  // close the session
  session.close();

  // close the driver.
  driver.close();
}
```

显式突变查询继承与隐式突变事务相同的行为。

如果未传入会话配置，默认情况下，该事务将被视为写入事务。

有关冲突，请参阅[使用锁定等待超时解决冲突](transactions-neptune.md#transactions-neptune-conflicts)。