1

我正在使用事务事件处理程序对已删除的节点进行安全检查,以确保当前用户是否被允许这样做。

为了确保我有正确的节点来检查我首先必须找出它是否具有某个属性,然后检查另一个属性的值,所以理想情况下代码应该是这样的:

        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

4

1 回答 1

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
}

您的代码段将为每个已删除的节点迭代此集合。

于 2013-09-03T13:34:01.303 回答