       out)))
 
 (defn notify-listeners [db-snap reports]
-  (doseq [listener (vals (get-in* db-snap [:listeners :tx-log]))]
+  (when (seq (get-in* db-snap [:listeners :entity]))
+    (doseq [eid (set (map first reports))]
+      (doseq [f (get-in* db-snap [:listeners :entity (get db-snap eid :id)])]
+        (f (entity db-snap eid)))))
+
+  (when (seq (get-in* db-snap [:listeners :entity-attr]))
+    (doseq [[eid attr] (set (map #(do [(first %) (second %)]) reports))]
+      (doseq [f (get-in* db-snap [:listeners :entity-attr (get db-snap eid :id) attr])]
+        (f (get db-snap eid attr)))))
+
+  (doseq [listener (get-in* db-snap [:listeners :tx-log])]
     (listener (remove nil? reports))))
 
 (defn transact! [db txs]

                   (add-index id attr val)
                   (remove-index id attr prev-val)))))))

(defn update [[db-snap reports] id attr f & args]
  {:pre [(not (many? db-snap attr))]}
  (assert (not (many? db-snap attr)) "Cannot update a :many attribute")
  (let [new-val (apply f (cons (get db-snap id attr) args))]

  (when-let [id (resolve-id db-snap id)]
    (get-in* db-snap [:data id])))

(defn get [db-snap id & args]
  (apply get* (cons (entity db-snap id) args)))

(defn get-in [db-snap id ks]
  (get-in* (entity db-snap id) ks))

(defn add-index [[db-snap reports] id a v]
