java - TransactionEventHandler 在 Node.setProperty() 上给出 javax.transaction.SystemException

标签 java transactions event-handling neo4j versioning

我正在尝试实现一个 TransactionEventHandler,就像 neo4j-versioning 中使用的那样为了创建时间机器风格,版本化的 Neo4j 数据库,现在使用 Neo4j 2.x。它因以下无限堆栈跟踪而失败:

javax.transaction.SystemException: TM has encountered some problem, please perform necessary action (tx recovery/restart)
at org.neo4j.kernel.impl.transaction.TxManager.assertTmOk(TxManager.java:349)
at org.neo4j.kernel.impl.transaction.TxManager.setRollbackOnly(TxManager.java:758)
at org.neo4j.kernel.TransactionEventHandlers.beforeCompletion(TransactionEventHandlers.java:120)
at org.neo4j.kernel.impl.core.TransactionEventsSyncHook.beforeCompletion(TransactionEventsSyncHook.java:68)
at org.neo4j.kernel.impl.transaction.TransactionImpl.doBeforeCompletion(TransactionImpl.java:368)
at org.neo4j.kernel.impl.transaction.TxManager.commit(TxManager.java:398)
at org.neo4j.kernel.impl.core.IsolatedTransactionTokenCreator.getOrCreate(IsolatedTransactionTokenCreator.java:61)
at org.neo4j.kernel.impl.core.TokenHolder.createToken(TokenHolder.java:114)
at org.neo4j.kernel.impl.core.TokenHolder.getOrCreateId(TokenHolder.java:102)
at org.neo4j.kernel.impl.api.store.DiskLayer.propertyKeyGetOrCreateForName(DiskLayer.java:367)
at org.neo4j.kernel.impl.api.store.CacheLayer.propertyKeyGetOrCreateForName(CacheLayer.java:370)
at org.neo4j.kernel.impl.api.StateHandlingStatementOperations.propertyKeyGetOrCreateForName(StateHandlingStatementOperations.java:939)
at org.neo4j.kernel.impl.api.DataIntegrityValidatingStatementOperations.propertyKeyGetOrCreateForName(DataIntegrityValidatingStatementOperations.java:67)
at org.neo4j.kernel.impl.api.OperationsFacade.propertyKeyGetOrCreateForName(OperationsFacade.java:397)
at org.neo4j.kernel.impl.core.NodeProxy.setProperty(NodeProxy.java:205)
...

这是我的测试:

@Test
public void test() {
  GraphDatabaseService graphDb = new TestGraphDatabaseFactory().newImpermanentDatabase();

  Node referenceNode = null;
  try (Transaction transaction = graphDb.beginTx()) {
    referenceNode = graphDb.createNode();
    transaction.success();
  }
  VersioningTransactionEventHandler versioningTransactionEventHandler = new VersioningTransactionEventHandler(referenceNode);
  graphDb.registerTransactionEventHandler(versioningTransactionEventHandler);

  try (Transaction tx = graphDb.beginTx()) {
    Node node = graphDb.createNode();
    tx.success();
  }
  graphDb.shutdown();
}

这是VersioningTransactionEventHandler:

public class VersioningTransactionEventHandler implements TransactionEventHandler<Object> {

  private final Node versionDataNode;
  
  public VersioningTransactionEventHandler(Node versionDataNode) {
    this.versionDataNode = versionDataNode;
  }

  @Override
  public Object beforeCommit(TransactionData data) throws Exception {
    versionDataNode.setProperty("foo", "bar"); // <- this causes the error
    return null;
  }

  @Override
  public void afterCommit(TransactionData data, Object state)
  {
  }

  @Override
  public void afterRollback(TransactionData data, Object state)
  {
  }
}

我在我的应用程序中使用 org.neo4j.neo4j-2.0.1org.neo4j.neo4j-kernel-2.0.1

为什么 setProperty() 会导致此错误?我该如何解决?非常感谢任何关于这里可能有问题的线索。


更新

正如 Michael Hunger 所建议的那样,我在传递节点之前执行了一个 setProperty(),但现在测试静静地挂起无限大,没有任何反应。在节点上设置什么属性键值对并不重要:

...
referenceNode = graphDb.createNode();
referenceNode.setProperty("foo", "bar");   // <- results in hang
referenceNode.setProperty("herp", "derp"); // <- results in hang also

...

还有线索吗?我只想在事务事件处理程序中操作一个节点,就像在 1.9 version 中那样。 , 但 Neo4j 2.x 没有在构造函数中传递的 GraphDatabaseService#getReferenceNode() 方法。

最佳答案

首先,您似乎想要在 TransactionEventHandler 的 afterCommit() 方法中调用 incrementTransactionVersion()。这样,您就知道在增加版本之前事务已成功提交。我假设循环是由于增加版本节点的版本属性导致另一个事务引起的。要解决此问题,您可以检查 TransactionData 以查看当前事务是否由版本 Node 的更改引起。这并不像它可能的那样简单,但这里有一些伪 Java(我什至没有测试它是否编译)说明了如何完成此操作:

Iterable<PropertyEntry<Node>> ii =  txData.assignedNodeProperties();
boolean doIncrementVersion = false;

for (PropertyEntry<Node> pEntry : txData.assignedNodeProperties()) {
    if (pEntry.key().equals("transactionVersion") {
        doIncrementVersion = true;
        break;
    }
}

if (doIncrementVersion) {
    incrementTransactionVersion();
}

希望这对您有所帮助!

关于java - TransactionEventHandler 在 Node.setProperty() 上给出 javax.transaction.SystemException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23906091/

相关文章:

Java - 包含/排除的简单平面

java - imageview源码在java文件和xml文件中?

java - Play Framework 反向路由

java - 当我的连接被管理禁用时提交的事务

javascript - Js 事件处理重叠元素不起作用。与范围有关吗?关于真/假?

java - 如何更改交互式代理中的时区?

java - 为什么 "@Transactional(propagation = propagation.NEVER)"不起作用?

java - dynamoDB 事务管理器

c# - 如何在 C# Winform 的文本框事件处理程序中禁用或捕获 "paste"或 "Control+V"事件?

javascript - meteor d3.js 通信事件