System.err.println ("SPLITTING SYNTHETIC KEY: "+key);
    public Node getNode (Key key) throws Exception {	Transactor tx = (Transactor) Thread.currentThread ();	// tx.timer.beginEvent ("getNode "+kstr);	// it would be a good idea to reuse key objects one day.	// Key key = new Key (dbmap, kstr);	// See if Transactor has already come across this node	Node node = tx.getVisitedNode (key);	if (node != null && node.getState() != Node.INVALID) {	    // tx.timer.endEvent ("getNode "+kstr);	    return node;	}	// try to get the node from the shared cache	node = (Node) cache.get (key);	if (node == null || node.getState() == Node.INVALID) {	    // The requested node isn't in the shared cache. Synchronize with key to make sure only one	    // version is fetched from the database.	    if (key instanceof SyntheticKey) {	    System.err.println ("SPLITTING SYNTHETIC KEY: "+key);	        Node parent = getNode (key.getParentKey ());	        Relation rel = parent.dbmap.getPropertyRelation (key.getID());	        if (rel == null || rel.groupby != null)	            node = parent.getGroupbySubnode (key.getID (), true);	        else if (rel != null)	            node = getNode (parent, key.getID (), rel);	        else	            node = null;	    } else	        node = getNodeByKey (tx.txn, key);		    if (node != null) {	        synchronized (cache) {	            Node oldnode = (Node) cache.put (node.getKey (), node);	            if (oldnode != null && oldnode.getState () != Node.INVALID && !(oldnode instanceof NullNode)) {	                cache.put (node.getKey (), oldnode);	                node = oldnode;	            }	        }  // synchronized	    }	}	if (node != null) {	    tx.visitCleanNode (key, node);	}	// tx.timer.endEvent ("getNode "+kstr);	return node;    }