Если вы использовали более ранние версии Neo4j через Java API с Java 6, вы, вероятно, имеете код, подобный следующему, чтобы гарантировать, что операции записи происходят внутри транзакции:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
public class StylesOfTx { public static void main( String[] args ) throws IOException { String path = "/tmp/tx-style-test" ; FileUtils.deleteRecursively( new File(path)); GraphDatabaseService db = new GraphDatabaseFactory().newEmbeddedDatabase( path ); Transaction tx = db.beginTx(); try { db.createNode(); tx.success(); } finally { tx.close(); } } } |
В Neo4j 2.0 Transaction начал расширять AutoCloseable, что означало, что вы можете использовать ‘try with resources’, и метод ‘close’ будет автоматически вызываться после завершения блока:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
public class StylesOfTx { public static void main( String[] args ) throws IOException { String path = "/tmp/tx-style-test" ; FileUtils.deleteRecursively( new File(path)); GraphDatabaseService db = new GraphDatabaseFactory().newEmbeddedDatabase( path ); try ( Transaction tx = db.beginTx() ) { Node node = db.createNode(); tx.success(); } } } |
Это работает довольно хорошо, хотя все еще возможно иметь транзакции в приложении, когда люди не используют этот синтаксис — старый стиль все еще допустим.
В книге Venkat Subramaniam’s Java 8 он предлагает альтернативный подход, в котором мы используем лямбда-подход:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public class StylesOfTx { public static void main( String[] args ) throws IOException { String path = "/tmp/tx-style-test" ; FileUtils.deleteRecursively( new File(path)); GraphDatabaseService db = new GraphDatabaseFactory().newEmbeddedDatabase( path ); Db.withinTransaction(db, neo4jDb -> { Node node = neo4jDb.createNode(); }); } static class Db { public static void withinTransaction(GraphDatabaseService db, Consumer<GraphDatabaseService> fn) { try ( Transaction tx = db.beginTx() ) { fn.accept(db); tx.success(); } } } } |
Функция ‘insideTransaction’ фактически будет работать с GraphDatabaseService или подобным, а не с этим классом Db, но для этого примера было проще поместить его туда.
Недостатком этого стиля является то, что вы не имеете явного контроля над транзакцией для обработки случая сбоя — предполагается, что если tx.success () не вызывается, то транзакция не удалась, и она откатывается. Я не уверен, какой% случаев действительно нуждается в таком мелкозернистом контроле.
Брайан Херт называет это « дырой в среднем паттерне », и я думаю, что мы увидим больше кода этого рода после того, как Java 8 будет выпущена и станет более широко используемой.