Right,

the same happens in Neo4j if you use cypher (comparable to SQL).

But if you use the java-API you kind are below the query language level 
(somewhere where you would never get in a rdbms) and there tx-management is 
manual.
In general we want to move away from the Java-API to a more query language 
based usage for all environments then you will have the same behavior as with 
RDBMs. When cypher is fast enough we'll get there :)

The only leak in this whole thing is when you use cypher from the java-API and 
return db-entities (like nodes, rels, paths) and want to access them later on. 
Then you are kind of between the two worlds.

I agree with you that the current transaction pattern is not really optimal, 
but I doubt it will change. So perhaps it makes sense to manage the tx at your 
service level entry-point with a single entry / exit and let the lower level 
methods just participate in the already running transaction.


HTH

Michael

Am 03.01.2014 um 14:40 schrieb M. David Allen <allen.m.da...@gmail.com>:

> Thanks to both of you for those responses.  They totally make sense.
> 
> Like many people, I'm riding the learning curve with graph databases.  I've 
> been doing RDBMS work forever, and only working with neo4j for about a year 
> and a half, and there's still so many things I don't know yet.
> 
> RE: the use of transactions, in the RDBMS world it's kind of a secret that 
> all reads are wrapped in transactions, but usually the programmer is ignorant 
> of that; they can just issue SELECT queries and get data back.   The DBMS 
> might do that inside of a transaction for all the reasons you provide, but 
> the user doesn't know it's happening.  Users do transactions more for when 
> they want to do things incrementally, be able to roll-back if something in 
> the middle fails, and so on.
> 
> So I won't take issue with the rationale, but perhaps some of this can be 
> hidden from the users over time.  With all of the benefits for read-only 
> operations that you cite, and with transactions being required everywhere, 
> perhaps there are opportunities where the API could do this for me.    If I 
> do have to do it everywhere (reads and writes) then while the Java 7 pattern 
> reduces the amount of code I'm writing, I'm still writing a lot of 
> boilerplate try/with blocks, and trying to remember to put tx.success() 
> before every exit point of the block (e.g. when my try block has 3 different 
> spots where it returns something from the method).
> 
> David
> 
> On Thursday, January 2, 2014 7:36:25 PM UTC-5, Michael Hunger wrote:
> 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+un...@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+un...@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.

Reply via email to