TransactionEventHandler在Node.setProperty()上给出javax.transaction.SystemException [英] TransactionEventHandler gives javax.transaction.SystemException on Node.setProperty()

查看:174
本文介绍了TransactionEventHandler在Node.setProperty()上给出javax.transaction.SystemException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  javax.transaction.SystemException:TM遇到一些问题,请执行必要的操作tx recovery / restart)
在org.neo4j.kernel.impl.transaction.TxManager.assertTmOk(TxManager.java:349)
在org.neo4j.kernel.impl.transaction.TxManager.setRollbackOnly(TxManager .java:758)
在org.neo4j.kernel.TransactionEventHandlers.beforeCompletion(TransactionEventHandlers.java:120)
在org.neo4j.kernel.impl.core.TransactionEventsSyncHook.beforeCompletion(TransactionEventsSyncHook.java:68 )
在org.neo4j.kernel.impl.transaction.TransactionImpl.doBeforeCompletion(TransactionImpl.java:368)
在org.neo4j.kernel.impl.transaction.TxManager.commit(TxManager.java:398 )
在org.neo4j.kernel.impl.core.IsolatedTransactionTokenCreator.getOrCreate(IsolatedTransactionTokenCreator.java:61)
在org.neo4j.kernel.impl.core.TokenHolder.createToken(TokenHolder.java:114 )
在org.neo4j.kernel.impl.co re.TokenHolder.getOrCreateId(TokenHolder.java:102)
在org.neo4j.kernel.impl.api.store.DiskLayer.propertyKeyGetOrCreateForName(DiskLayer.java:367)
在org.neo4j.kernel。 impl.api.store.CacheLayer.propertyKeyGetOrCreateForName(CacheLayer.java:370)
在org.neo4j.kernel.impl.api.StateHandlingStatementOperations.propertyKeyGetOrCreateForName(StateHandlingStatementOperations.java:939)
在org.neo4j。 kernel.impl.api.DataIntegrityValidatingStatementOperations.propertyKeyGetOrCreateForName(DataIntegrityValidatingStatementOperations.java:67)
在org.neo4j.kernel.impl.api.OperationsFacade.propertyKeyGetOrCreateForName(OperationsFacade.java:397)
在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实现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); //< - 这会导致错误
返回null;
}

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

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

我正在使用 org.neo4j.neo4j-2.0.1 org.neo4j.neo4j-kernel-2.0。 1 在我的应用程序。



为什么 setProperty()导致此错误?我该怎么解决?






更新


$ b $由于Michael Hunger建议我在传递节点之前先做了一个 setProperty(),但现在测试静默挂起无穷远,没有任何反应。在节点上设置什么属性键值对无关紧要:

  ... 
referenceNode = graphDb.createNode();
referenceNode.setProperty(foo,bar); //< - result in hang
referenceNode.setProperty(herp,derp); //< - 结果也挂起

...

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

解决方案

我发现一个解决方法,最后一次挂起,当我打电话 setProperty() in beforeCommit()。似乎它只发生在非写入事务(我认为 beforeCommit()仅在写作操作)?



所以,如果我在进行属性设置之前检查,挂起消失:

  ... 

@Override
public Object beforeCommit(TransactionData data)throws异常{
if(containsWriteChanges(data)){
versionDataNode .setProperty(foo,bar);
}
返回null;
}

private boolean containsWriteChanges(TransactionData data){
return data.assignedNodeProperties()。iterator()。hasNext()
|| data.assignedRelationshipProperties()。iterator()。hasNext()
|| data.createdNodes()。iterator()。hasNext()
|| data.createdRelationships()。iterator()。hasNext()
|| data.deletedNodes()。iterator()。hasNext()
|| data.deletedRelationships()。iterator()。hasNext()
|| data.removedNodeProperties()。iterator()。hasNext()
|| 。data.removedRelationshipProperties()迭代()hasNext();
}

...


I'm trying to implement a TransactionEventHandler like the one used in neo4j-versioning in order to create a time-machine style, versioned Neo4j database, now using Neo4j 2.x. It fails with the following infinite stack trace:

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)
...

This is my test:

@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();
}

This is the 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)
  {
  }
}

I'm using org.neo4j.neo4j-2.0.1 and org.neo4j.neo4j-kernel-2.0.1 in my application.

Why is the setProperty() causing this error? How can I fix it? Any clues to what may be wrong here is greatly appreciated.


Update

As Michael Hunger suggested I did a setProperty() before passing the node in, but now the test silently hangs for infinity and nothing happens. It doesn't matter what property key-value pair is set on the node:

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

...

Still any clues? I just want to manipulate a node while inside the transaction event handler like it was done in the 1.9 version, but Neo4j 2.x doesn't have the GraphDatabaseService#getReferenceNode() method which is passed in the constructor there.

解决方案

I found a workaround the last hang happening when I called setProperty() in beforeCommit(). It seems it only happens on non-write transactions (I thought beforeCommit() was only called on write operations)?

So then, if I check that before doing the property setting, the hanging disappears:

...

@Override
public Object beforeCommit(TransactionData data) throws Exception {
  if (containsWriteChanges(data)) {
    versionDataNode.setProperty("foo", "bar");
  }
  return null;
}

private boolean containsWriteChanges(TransactionData data) {
  return data.assignedNodeProperties().iterator().hasNext()
          || data.assignedRelationshipProperties().iterator().hasNext()
          || data.createdNodes().iterator().hasNext()
          || data.createdRelationships().iterator().hasNext()
          || data.deletedNodes().iterator().hasNext()
          || data.deletedRelationships().iterator().hasNext()
          || data.removedNodeProperties().iterator().hasNext()
          || data.removedRelationshipProperties().iterator().hasNext();
}

...

这篇关于TransactionEventHandler在Node.setProperty()上给出javax.transaction.SystemException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆