Thanks a lot Johannes for chiming in. Adding transactions for reads is mostly about creating the foundations for - repeatable reads, - better resource management - allowing support for more isolation levels - better automatic locking
The move from try - finally to try - with and AutoClosable was something that came after Java7 was required, just a easier to use pattern. Currently in Neo4j the approach is fail by default, other tx-systems use succeed by default and offer something like tx.setRollbackOnly() to mark for failure. According to the core team this is by intent but unfortunately makes it easy to miss the necessary tx.success() call. :( so the current pattern required is: try (Transaction tx = db.beginTx()) { do stuff tx.success(); } HTH Mcihael Am 02.01.2014 um 23:41 schrieb Johannes Mockenhaupt <goo...@jotomo.de>: > On 12/31/2013 04:12 PM, M. David Allen wrote: >> Just curious, what's the thinking behind requiring transactions for reads? > > Since nobody else answered yet I'll take a stab at it :-) > > As far as I know the reason for requiring transaction for read > operations is optimization: fetched resources can be released after the > transactional context has been closed. A nice side-effect is > consistency: your read operations will be unaffected by write > transactions that are going on in parallel. > >> Also, some documentation updates might be appropriate. For example: >> >> http://api.neo4j.org/current/org/neo4j/graphdb/NotInTransactionException.html >> >> public class NotInTransactionException >> extends RuntimeException > <http://docs.oracle.com/javase/7/docs/api/java/lang/RuntimeException.html?is-external=true> >> >> Thrown when attempting to modify the graph outside of a transaction. >> > > Thanks for catching that, the docs have been updated but that spot has > been missed. I have opened a pull request for an update of that JavaDoc > which has already been merged. > >> Finally, I noticed that with 2.0, apparently the code wants you to use >> try/with, instead of try/finally, e.g. >> >> |try ( Transaction tx = graphDb.beginTx() ) { blah(); } >> >> I'm also curious about that decision, since it requires I choose between >> looking >> at deprecation warnings on my use of tx.finish() or trying to upgrade all my >> developer's IDEs to java7 code style compliance. > > I like the reduction of redundant code this change brings, but then > again, I don't have a migrate a (big) code base too it ;-) > > Johannes > >> On Tuesday, December 31, 2013 10:07:08 AM UTC-5, Michael Hunger wrote: >> >> Hi >> >> Read operation on the database and nodes and relationships now >> require transactions >> >> Probably most sensible to wrap the tx around the entry point to your >> service layer. >> >> HTH >> >> Michael >> >> Sent from mobile device >> >> Am 31.12.2013 um 15:53 schrieb "M. David Allen" <allen....@gmail.com >> <javascript:>>: >> >>> I'm in the middle of retrofitting neo4j code that was running on >>> 1.9.3 to 2.0.0. This is all happening under windows, jdk1.7.0_45, >>> and eclipse. >>> >>> I expected some teething problems and cut-overs; here's one I've >>> run into: >>> >>> org.neo4j.graphdb.NotInTransactionException >>> at >>> >>> org.neo4j.kernel.impl.persistence.PersistenceManager.getResource(PersistenceManager.java:214) >>> at >>> >>> org.neo4j.kernel.impl.persistence.PersistenceManager.currentKernelTransaction(PersistenceManager.java:84) >>> at >>> >>> org.neo4j.kernel.impl.core.ThreadToStatementContextBridge.transaction(ThreadToStatementContextBridge.java:53) >>> at >>> >>> org.neo4j.kernel.impl.core.ThreadToStatementContextBridge.instance(ThreadToStatementContextBridge.java:47) >>> at >>> org.neo4j.kernel.impl.core.NodeProxy.hasProperty(NodeProxy.java:346) >>> at >>> blah.blah.mypackage.MyStorage.isMyObjectNode(Neo4JStorage.java:219) >>> at >>> blah.blah.mypackage.MyFactory.newObject(Neo4JPLUSObjectFactory.java:190) >>> at >>> blah.blah.mypackage.MyFactory.listWorkflows(Neo4JStorage.java:933) >>> >>> I can make it happy by wrapping the methods below in a >>> transaction, but I'm pretty sure that's not the right thing to do. >>> >>> Here's the relevant method: >>> >>> public static boolean isMyObjectNode(Node n) { >>> return n != null && n.hasProperty(PROP_PLUSOBJECT_ID) && >>> n.hasProperty(PROP_TYPE) && n.hasProperty(PROP_SUBTYPE); >>> } >>> >>> (Context: all of those PROP_TYPE, etc are all public static final >>> String) >>> >>> The "newObject" method in my package is just creating one of my >>> domain objects out of a node. In order to do that, it needs to >>> check which kind of node it's dealing with. I'd rather not paste >>> that code because it's involved and includes many other subclasses >>> that makes the rabbit hole deeper. Suffice to say I'm sure that >>> it's just creating my domain objects, and not modifying anything >>> in the graph. >>> >>> The "listWorkflows" method looks like this: >>> >>> public static List<MyWorkflow> listWorkflows(User user, int >>> maxReturn) throws MyException { >>> if(maxReturn <= 0 || maxReturn > 1000) maxReturn = 100; >>> >>> String query = "start n=node:node_auto_index(type=\"" + >>> MyWorkflow.TYPE_WORKFLOW + "\") " + >>> "where has(n.oid) " + >>> "return n " + >>> "limit " + maxReturn; >>> >>> Iterator<Node> ns = Neo4JStorage.execute(query).columnAs("n"); >>> ArrayList<MyWorkflow> wfs = new ArrayList<MyWorkflow>(); >>> >>> while(ns.hasNext()) { >>> MyObject o = MyFactory.newObject(ns.next()); >>> if(o.isWorkflow()) wfs.add((MyWorkflow)o); >>> else { >>> log.warning("Returned non-workflow " + o + " from >>> workflow query!"); >>> } >>> } >>> >>> return wfs; >>> } // End listWorkflows >>> >>> Indeed this code (and its caller) doesn't happen within a >>> transaction, but it shouldn't need to -- no modification is going >>> on here. >>> >>> Lastly -- yes, I know about labels, and how labels would probably >>> be a better way to do this. I'm planning on exploiting that, but >>> the first thing to do is to get the current code base working on >>> the new release, and I've got other fish to fry (like cypher query >>> syntax updates to get rid of "?") before I get to using labels. >>> >>> Thanks! >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Neo4j" group. >>> To unsubscribe from this group and stop receiving emails from it, >>> send an email to neo4j+un...@googlegroups.com <javascript:>. >>> For more options, visit https://groups.google.com/groups/opt_out >>> <https://groups.google.com/groups/opt_out>. >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Neo4j" group. >> To unsubscribe from this group and stop receiving emails from it, send >> an email to neo4j+unsubscr...@googlegroups.com. >> For more options, visit https://groups.google.com/groups/opt_out. > > -- > You received this message because you are subscribed to the Google Groups > "Neo4j" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to neo4j+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/groups/opt_out. -- You received this message because you are subscribed to the Google Groups "Neo4j" group. To unsubscribe from this group and stop receiving emails from it, send an email to neo4j+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.