TransactionEventHandler在Node.setProperty()上给出javax.transaction.SystemException [英] TransactionEventHandler gives javax.transaction.SystemException on Node.setProperty()
问题描述
我正在尝试实现一个 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屋!