我正在使用事务事件处理程序对已删除的节点执行安全检查,以确保是否允许当前用户执行此操作。
为了确保我有正确的节点来检查我首先必须找出它是否具有某个属性,然后检查另一个属性的值,所以理想情况下代码应该是这样的:
graphDatabaseService.registerTransactionEventHandler(new TransactionEventHandler.Adapter<Object>() {
@Override
public Object beforeCommit(TransactionData data) throws Exception {
for (Node node : data.deletedNodes()) {
if (node.hasProperty("checkProperty")){
if (node.hasProperty("propertyToCheck")){
String value = (String) node.getProperty("propertyToCheck");
... do checking on value
}
}
}
return null;
}
但是这个例外失败
Caused by: java.lang.IllegalStateException: Node[11] has been deleted in this tx
at org.neo4j.kernel.impl.core.WritableTransactionState$CowEntityElement.assertNotDeleted(WritableTransactionState.java:141)
at org.neo4j.kernel.impl.core.WritableTransactionState$CowEntityElement.getPropertyAddMap(WritableTransactionState.java:129)
at org.neo4j.kernel.impl.core.WritableTransactionState$CowNodeElement.getPropertyAddMap(WritableTransactionState.java:155)
at org.neo4j.kernel.impl.core.WritableTransactionState.getCowPropertyAddMap(WritableTransactionState.java:529)
at org.neo4j.kernel.impl.core.Primitive.hasProperty(Primitive.java:306)
at org.neo4j.kernel.impl.core.NodeImpl.hasProperty(NodeImpl.java:53)
at org.neo4j.kernel.impl.core.NodeProxy.hasProperty(NodeProxy.java:160)
我找到的唯一解决方法是:
for (Node node : data.deletedNodes()) {
boolean check = false;
String valueToCheck = null;
for (PropertyEntry prop : data.removedNodeProperties()) {
if (node.equals(prop.entity())) {
if (prop.key().equals("checkProperty")) {
check = true;
}
if (prop.key().equals("propertyToCheck")) {
valueToCheck = (String) prop.previouslyCommitedValue();
}
}
}
if (check){
... do checking on value
}
}
但是这会通过所有已删除的属性,所以这显然不是一个很好的解决方案。
所以我的问题是:有更好的方法吗?
使用neo4j 1.9.3
答案 0 :(得分:3)
由于TransactionEventHandler#beforeCommit
中的代码本身是事务的一部分,因此您无法访问已删除节点或关系上的任何属性。正如您所发现的,访问已删除属性的唯一方法是通过TransactionData#removedNodeProperties()
和TransactionData#removedRelationshipProperties()
。
您可以通过在removedNodeProperties()
上运行一次迭代来优化代码(仅使用下面的伪代码):
for (PropertyEntry<Node> pe: data.removedNodeProperties()) {
if (pe.key().equals("checkProperty")) {
runCheckForDeletedNodeAndValue(pe.entity(), pe.previouslyCommitedValue())
}
}
public void runCheckForDeletedNodeAndValue(Node node, Object oldValue) {
// throw exception if current user is not allowed to delete
// this will rollback whole transaction
}
您的代码段将针对每个已删除的节点迭代此集合。