Hello friends,

I'm upgrading some code of mine to use Neo4J 2.0, which now requires a
transaction on _reads_ as well as writes for anything dealing with
Node/Relationships.  (It used to be reading didn't require a tx)

For those that don't know Neo4J nodes and edges have a Map<String,Object>
property inside them, and that's where you keep your data that would
normally end up in a domain object as fields.

A recent suggestion from the Neo4J site for working with Domain objects
(Let's say, User.class for example) is to store the underlying node in the
domain object and have getters/setters that work on the underlying node's
property map.  I've used that suggestion this evening and I'm wondering if
this is the right decision.  Here's more information:

A graph service is required to create transactions.  I have this available
by IOC, no problem.
I also have an IOC'd UserDAO which generates User.class objects from the
graph database. Again, no problem there.  Once the UserDAO returns a
User.class to whoever asked for it, that User.class can't be read/written
to without a transaction from the graph service.

I don't want the domain objects to have a handle on the graph service, that
doesn't seem right to me. I can't advise the domain objects because they
are not covered by the IOC framework.

Basically anything that can touch the domain object now has to have the
ability to create a transaction.  This seems like an ideal job for a custom
@Neo4JTransactional, which I'd have to add to every page/component/service
that might touch a User.class.

Whereas with T5Hibernate, @CommitAfter is optional, this new
@Neo4JTransactional would be required or else it will fail.  There are
plenty of times I just needed to read fields from a bean when using
Hibernate, and I didn't have to worry about a transaction.

For classes that are not 'covered' by IOC, such as Test classes, I'd have
to get my transaction elsewhere, probably from the same DAO I get the
User.class from.

The Question:
So does a custom Advise annotation seem like the right way to go?  I'd
create a tx before the method invocation, invoke it and then call
tx.success afterwards, for all methods in a class.  It would be a pain (and
intrusive) to have to mark each method that could possibly read or write to
the domain object, so I'd want to Advise the class on all methods.  Luckily
Neo4J doesn't seem to care about nested tx, so that shouldn't be a problem!

I've looked briefly at how Spring's Neo4J Data framework handles this.
 Looks like it might work, but I can't add that dependency to the project
right now.  I could maybe borrow some code though.


The other option, which I had been using previously, is this:
===================
The DAO returns a User.class that has no idea what a Neo4J Node is.  Neo4J
can't 'detach' a node it seems, so I iterated through the
Map<String,Object> and set all the properties manually in the User.class

Now a T5 page or service comes along and mucks with the User object, but to
save it back to the graph db I have to essentially give the User object
back to the DAO and manually reattach it (lookup the original node and
update properties).

1) This creates a lot of boiler plate for the detach/re-attach.
2) This becomes messy if the property that is getting updated is the same
one we used to look up the Node (i.e. if the lookup value was the email
address, which can be changed)  I don't really have that case now, but I
could foresee that problem with the other domain objects.
===================


Thanks for any tips or wisdom,

Dan

Reply via email to