title: How to properly return a StatementResult with a Transaction function?
body: <p>Maybe the title itself is enough to express my confusion. In one hand I read a lot that using transaction functions is the recommended way to use the neo4j java driver. </p>
  
  <p>See  <a href="https://neo4j.com/developer/java/#neo4j-java-driver" rel="nofollow noreferrer">Neo4j Java Driver</a> </p>
  
  <p>On the other hand, I see examples of codes, such as in <a href="https://neo4j.com/docs/api/java-driver/current/" rel="nofollow noreferrer">Neo4j Java Driver 1.7 API</a> where there is no transaction (or maybe it's implicit), and I like the idea of having a <code>StatementResult</code> and iterating on it.</p>
  
  <p>So what should I do ?   </p>
  
  <p>Is there a way of having the iterator of an auto-commit transation in a transaction function ? Should I keep using the <code>execute()</code> function, the <code>session.writeTransaction()</code> function ?  </p>
  
  <p>It seems to me that there is a lot of way of running a simple request, but it can't figure why, or if theses methods can be a bit mixed up.</p>
  
  <p>I'm not very happy with <code>writeTransaction</code> if I can only get a String out of it.</p>
  
  <p>There is also the <a href="https://github.com/neo4j/neo4j-java-driver/tree/1.7/examples/src/main/java/org/neo4j/docs/driver" rel="nofollow noreferrer">GitHub examples</a> for this driver, especially <a href="https://github.com/neo4j/neo4j-java-driver/blob/1.7/examples/src/main/java/org/neo4j/docs/driver/ResultRetainExample.java" rel="nofollow noreferrer">the ResultRetain</a> with the 'Record' object which is closer of what I'm looking for but without any iterator. It allows data to be extracted with accessers. Another close example is the <a href="https://github.com/neo4j/neo4j-java-driver/blob/1.7/examples/src/main/java/org/neo4j/docs/driver/ResultConsumeExample.java" rel="nofollow noreferrer">ResultConsume</a> but still no iterator.</p>
  
  <p>Based on these examples I wrote the following code, it works as expected, with generator and getters.</p>
  
  <pre><code>import org.neo4j.driver.v1.Record;
  import org.neo4j.driver.v1.Session;
  import org.neo4j.driver.v1.StatementResult;
  import org.neo4j.driver.v1.Transaction;
  import org.neo4j.driver.v1.TransactionWork;
  
  
  public class InitializeUser extends Logger{
    StatementResult result;
  
    public void getUserForInitialization(){
      try ( Session session = driver.session() )
      {
        result = session.readTransaction( new TransactionWork&lt;StatementResult&gt;()
          {
              @Override
              public StatementResult execute( Transaction tx )
              {
                  return tx.run(
                    "MATCH (a{initialized:false}) "+
                    "RETURN a.username as username");
              }
          } );
      }
    }
  
    public void readGenerator(){
      while (result.hasNext())
      {
          Record record = result.next();
          System.out.println(record.get("username").asString());
      }
    }
  }
  </code></pre>
  
  <p>I'm not sure if it's worse or better than following the <a href="https://github.com/neo4j/neo4j-java-driver/blob/1.7/examples/src/main/java/org/neo4j/docs/driver/ResultRetainExample.java" rel="nofollow noreferrer">ResultRetain</a> or the <a href="https://github.com/neo4j/neo4j-java-driver/blob/1.7/examples/src/main/java/org/neo4j/docs/driver/ResultConsumeExample.java" rel="nofollow noreferrer">ResultConsume</a> example but it has a generator, getters and what I think is transaction functions. I'm still very open to suggestions and explanations.  </p>
  
  <p>If someone could explain a bit the mechanic behind <code>TransactionWork()</code>, <code>execute()</code>, and what is the difference between <code>readTransaction()</code>, <code>writeTransaction()</code>, <code>run()</code> and <code>beginTransaction()</code>, I would be delighted.</p>
  
  <hr>
  
  <p>Neo4j Java Driver</p>
  
  <pre><code>import org.neo4j.driver.v1.AuthTokens;
  import org.neo4j.driver.v1.Driver;
  import org.neo4j.driver.v1.GraphDatabase;
  import org.neo4j.driver.v1.Session;
  import org.neo4j.driver.v1.StatementResult;
  import org.neo4j.driver.v1.Transaction;
  import org.neo4j.driver.v1.TransactionWork;
  
  import static org.neo4j.driver.v1.Values.parameters;
  
  public class HelloWorldExample implements AutoCloseable
  {
      private final Driver driver;
  
      public HelloWorldExample( String uri, String user, String password )
      {
          driver = GraphDatabase.driver( uri, AuthTokens.basic( user, password ) );
      }
  
      @Override
      public void close() throws Exception
      {
          driver.close();
      }
  
      public void printGreeting( final String message )
      {
          try ( Session session = driver.session() )
          {
              String greeting = session.writeTransaction( new TransactionWork&lt;String&gt;()
              {
                  @Override
                  public String execute( Transaction tx )
                  {
                      StatementResult result = tx.run( "CREATE (a:Greeting) " +
                                                       "SET a.message = $message " +
                                                       "RETURN a.message + ', from node ' + id(a)",
                              parameters( "message", message ) );
                      return result.single().get( 0 ).asString();
                  }
              } );
              System.out.println( greeting );
          }
      }
  
      public static void main( String... args ) throws Exception
      {
          try ( HelloWorldExample greeter = new HelloWorldExample( "bolt://localhost:7687", "neo4j", "password" ) )
          {
              greeter.printGreeting( "hello, world" );
          }
      }
  }
  </code></pre>
  
  <hr>
  
  <p>Neo4j Java Driver 1.7 API</p>
  
  <pre><code>import org.neo4j.driver.v1.*;
  
  import static org.neo4j.driver.v1.Values.parameters;
  
  public class SmallExample
  {
      // Driver objects are thread-safe and are typically made available application-wide.
      Driver driver;
  
      public SmallExample(String uri, String user, String password)
      {
          driver = GraphDatabase.driver(uri, AuthTokens.basic(user, password));
      }
  
      private void addPerson(String name)
      {
          // Sessions are lightweight and disposable connection wrappers.
          try (Session session = driver.session())
          {
              // Wrapping Cypher in an explicit transaction provides atomicity
              // and makes handling errors much easier.
              try (Transaction tx = session.beginTransaction())
              {
                  tx.run("MERGE (a:Person {name: {x}})", parameters("x", name));
                  tx.success();  // Mark this write as successful.
              }
          }
      }
  
      private void printPeople(String initial)
      {
          try (Session session = driver.session())
          {
              // Auto-commit transactions are a quick and easy way to wrap a read.
              StatementResult result = session.run(
                      "MATCH (a:Person) WHERE a.name STARTS WITH {x} RETURN a.name AS name",
                      parameters("x", initial));
              // Each Cypher execution returns a stream of records.
              while (result.hasNext())
              {
                  Record record = result.next();
                  // Values can be extracted from a record by index or name.
                  System.out.println(record.get("name").asString());
              }
          }
      }
  
      public void close()
      {
          // Closing a driver immediately shuts down all open connections.
          driver.close();
      }
  
      public static void main(String... args)
      {
          SmallExample example = new SmallExample("bolt://localhost:7687", "neo4j", "password");
          example.addPerson("Ada");
          example.addPerson("Alice");
          example.addPerson("Bob");
          example.printPeople("A");
          example.close();
      }
  }
  </code></pre>
  
  <hr>
  
  <p>Neo4j Java Driver ResultRetainExample</p>
  
  <pre><code>import java.util.List;
  
  import org.neo4j.driver.v1.Record;
  import org.neo4j.driver.v1.Session;
  import org.neo4j.driver.v1.Transaction;
  import org.neo4j.driver.v1.TransactionWork;
  
  import static org.neo4j.driver.v1.Values.parameters;
  // end::result-retain-import[]
  
  public class ResultRetainExample extends BaseApplication
  {
      public ResultRetainExample( String uri, String user, String password )
      {
          super( uri, user, password );
      }
  
      // tag::result-retain[]
      public int addEmployees( final String companyName )
      {
          try ( Session session = driver.session() )
          {
              int employees = 0;
              List&lt;Record&gt; persons = session.readTransaction( new TransactionWork&lt;List&lt;Record&gt;&gt;()
              {
                  @Override
                  public List&lt;Record&gt; execute( Transaction tx )
                  {
                      return matchPersonNodes( tx );
                  }
              } );
              for ( final Record person : persons )
              {
                  employees += session.writeTransaction( new TransactionWork&lt;Integer&gt;()
                  {
                      @Override
                      public Integer execute( Transaction tx )
                      {
                          tx.run( "MATCH (emp:Person {name: $person_name}) " +
                                  "MERGE (com:Company {name: $company_name}) " +
                                  "MERGE (emp)-[:WORKS_FOR]-&gt;(com)",
                                  parameters( "person_name", person.get( "name" ).asString(), "company_name",
                                          companyName ) );
                          return 1;
                      }
                  } );
              }
              return employees;
          }
      }
  
      private static List&lt;Record&gt; matchPersonNodes( Transaction tx )
      {
          return tx.run( "MATCH (a:Person) RETURN a.name AS name" ).list();
      }
  
      // end::result-retain[]
  
  }
  </code></pre>
  
  <hr>
  
  <p>Neo4j Java Driver ResultConsumeExample</p>
  
  <pre><code>import java.util.ArrayList;
  import java.util.List;
  
  import org.neo4j.driver.v1.Session;
  import org.neo4j.driver.v1.StatementResult;
  import org.neo4j.driver.v1.Transaction;
  import org.neo4j.driver.v1.TransactionWork;
  // end::result-consume-import[]
  
  public class ResultConsumeExample extends BaseApplication
  {
      public ResultConsumeExample( String uri, String user, String password )
      {
          super( uri, user, password );
      }
  
      // tag::result-consume[]
      public List&lt;String&gt; getPeople()
      {
          try ( Session session = driver.session() )
          {
              return session.readTransaction( new TransactionWork&lt;List&lt;String&gt;&gt;()
              {
                  @Override
                  public List&lt;String&gt; execute( Transaction tx )
                  {
                      return matchPersonNodes( tx );
                  }
              } );
          }
      }
  
      private static List&lt;String&gt; matchPersonNodes( Transaction tx )
      {
          List&lt;String&gt; names = new ArrayList&lt;&gt;();
          StatementResult result = tx.run( "MATCH (a:Person) RETURN a.name ORDER BY a.name" );
          while ( result.hasNext() )
          {
              names.add( result.next().get( 0 ).asString() );
          }
          return names;
      }
      // end::result-consume[]
  
  }
  </code></pre>