CINXE.COM
Transactions | Ebean
<!doctype html> <html lang="en"> <head> <title>Transactions | Ebean</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="shortcut icon" href="/images/favicon.ico"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto|Source+Sans+Pro|Ubuntu&display=swap"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous"> <link rel="stylesheet" href="/css/reset3.css"> <link rel="stylesheet" href="/css/site3.css"> <link rel="stylesheet" href="/css/pygments3.css"> </head> <body> <div id="main"> <div id="banner"> <header> <nav id="top"> <h1 id="breadcrumb"> <a class="nav-logo" href="/"><img src="/images/logo-200.png" height="35"></a> <a href="/docs">Documentation</a><span class="sep"> / </span><span class="last">Transactions</span> </h1> <ul> <li><a onclick="toggleTheme();" title="switch dark light theme"><i class="fas fa-adjust"></i></a></li> </ul> </nav> </header> </div> <div class="grid grid-docs"> <aside> <nav class="side"> <ul> <li class="nav0 "> <a href="/docs/getting-started">Getting started</a> </li> <li class="nav0 "> <a href="/docs/intro">Introduction</a> </li> <li class="nav0 active"> <a class="active" href="/docs">Documentation</a> <ul> <li class="nav1 "> <a href="/docs/best-practice">Best practice</a> </li> <li class="nav1 "> <a href="/docs/query">Query</a> </li> <li class="nav1 "> <a href="/docs/persist">Persist</a> </li> <li class="nav1 active"> <a class="active" href="/docs/transactions">Transactions</a> <ul class="nav"> <li class="nav1 active"> <a class="active" href="/docs/transactions/">Introduction</a> <ul class="nav nav-scroll"> <li><a href="#transactional">@Transactional</a></li> <li><a href="#current">Transaction.current()</a></li> <li><a href="#beginTransaction">beginTransaction()</a></li> <li><a href="#end">commit(), rollback(), end()</a></li> <li><a href="#commitAndContinue">commitAndContinue()</a></li> <li><a href="#setRollbackOnly">setRollbackOnly()</a></li> <li><a href="#createTransaction">createTransaction()</a></li> <li><a href="#implicit">Implicit transactions</a></li> </ul> </li> <li class="nav1 "> <a href="/docs/transactions/batch">Batch</a> </li> <li class="nav1 "> <a href="/docs/transactions/scopes">Scopes</a> </li> <li class="nav1 "> <a href="/docs/transactions/savepoints">Savepoints</a> </li> <li class="nav1 "> <a href="/docs/transactions/spring">Spring</a> </li> <li class="nav1 "> <a href="/docs/transactions/jta">JTA</a> </li> </ul> </li> <li class="nav1 "> <a href="/docs/mapping">Mapping</a> </li> <li class="nav1 "> <a href="/docs/ddl-generation">DDL & Migrations</a> </li> <li class="nav1 "> <a href="/docs/logging">Logging</a> </li> <li class="nav1 "> <a href="/docs/testing">Testing</a> </li> <li class="nav1 "> <a href="/docs/read-replicas">Read Replicas</a> </li> <li class="nav1 "> <a href="/docs/database">Database platforms</a> </li> <li class="nav1 "> <a href="/docs/multi-database">Multiple databases</a> </li> <li class="nav1 "> <a href="/docs/kotlin">Kotlin</a> </li> <li><a href="/docs/tuning">Tuning</a></li> <li class="nav1 "> <a href="/docs/features">Features</a> </li> </ul> </li> <li class="nav0 "> <a href="/support">Getting help</a> </li> <li class="nav0 "> <a target="_blank" href="/apidoc/13">API Javadoc</a> </li> <li class="nav0 "> <a href="/videos">Videos</a> </li> <li class="nav0 "> <a href="/docs/upgrading">Upgrading</a> </li> <li class="nav0 "> <a href="/releases">Releases</a> </li> </ul> </nav> </aside> <article> <form action="https://www.google.com/search" method="get" class="inline-form"> <input type="hidden" name="as_sitesearch" value="ebean.io"> <div id="page-search"> <div class="input-group"> <input class="frm" name="q" id="searchinput" type="text" placeholder="Search... (press 's' to focus)" data-placeholder-focus="Search... (use '↑', '↓' and '⏎' to select results)" data-placeholder-blur="Search... (press 's' to focus)" autocomplete="off"> <div class="input-group-btn"> <button class="frm" type="submit"><i class="fas fa-search"></i></button> </div> </div> <div id="page-search-results" style="display: none;"> <ul id="search-results-container" class="search-results"><li class=" active"><a href="/docs" title="Docs"><span style="color:#777;">Docs</span> Documentation </a></li><li class=""><small style="color:#999;">And 101 more...</small></li></ul> </div> </div> </form> <h2 id="transactional">@Transactional</h2> <p> Annotate methods with <code>@Transactional</code> and all database queries and changes will occur in a single transaction. </p> <p> The transaction will use the <a href="/docs/intro/database/#default">default database</a>, be put into the "thread local scope" and will commit if the methods completes successfully. </p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="nd">@Transactional</span> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">process</span><span class="o">(</span><span class="n">OffsetDateTime</span> <span class="n">startOffset</span><span class="o">)</span> <span class="o">{</span> <span class="o">...</span> <span class="n">customer</span><span class="o">.</span><span class="na">save</span><span class="o">();</span> <span class="n">contact</span><span class="o">.</span><span class="na">save</span><span class="o">();</span> <span class="o">}</span> </pre></div> </div> <h2 id="current">Transaction.current()</h2> <p> Use <code>Transaction.current()</code> to return the current transaction from "thread local scope" of the <a href="/docs/intro/database/#default">default database</a>. </p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="nd">@Transactional</span> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">process</span><span class="o">(</span><span class="n">OffsetDateTime</span> <span class="n">startOffset</span><span class="o">)</span> <span class="o">{</span> <span class="o">...</span> <span class="n">Transaction</span> <span class="n">txn</span> <span class="o">=</span> <span class="n">Transaction</span><span class="o">.</span><span class="na">current</span><span class="o">();</span> <span class="o">...</span> <span class="o">}</span> </pre></div> </div> <p> use <code>database.currentTransaction()</code> to return the current transaction for a given database that is typically not the default database. </p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="n">Database</span> <span class="n">otherDb</span> <span class="o">=</span> <span class="n">DB</span><span class="o">.</span><span class="na">byName</span><span class="o">(</span><span class="s">"other"</span><span class="o">);</span> <span class="n">Transaction</span> <span class="n">txn</span> <span class="o">=</span> <span class="n">otherDb</span><span class="o">.</span><span class="na">currentTransaction</span><span class="o">();</span> </pre></div> </div> <h2 id="beginTransaction">beginTransaction()</h2> <p> As an alternative to <em>@Transactional</em> we can use <code>beginTransaction()</code> to start an explicit transaction. The transaction is put into the "thread local scope" and used by any subsequent queries, save, delete etc. </p> <p> We should use a <em>try with resources</em> block to ensure that the transaction is closed if any error occurs in the block. </p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="k">try</span> <span class="o">(</span><span class="n">Transaction</span> <span class="n">transaction</span> <span class="o">=</span> <span class="n">DB</span><span class="o">.</span><span class="na">beginTransaction</span><span class="o">())</span> <span class="o">{</span> <span class="c1">// do stuff...</span> <span class="n">Customer</span> <span class="n">customer</span> <span class="o">=</span> <span class="o">...</span> <span class="n">customer</span><span class="o">.</span><span class="na">save</span><span class="o">();</span> <span class="n">Order</span> <span class="n">order</span> <span class="o">=</span> <span class="o">...</span> <span class="n">order</span><span class="o">.</span><span class="na">save</span><span class="o">();</span> <span class="n">transaction</span><span class="o">.</span><span class="na">commit</span><span class="o">();</span> <span class="o">}</span> </pre></div> </div> <h4 id="kotlinUse">Kotlin transaction.use { }</h4> <p> Kotlin <code>use</code> is used similarly to <em>try with resources</em> to ensure the transaction is closed. </p> <div class="syntax kotlin"><div class="highlight"><pre><span></span><span class="n">DB</span><span class="p">.</span><span class="n">beginTransaction</span><span class="p">().</span><span class="n">use</span> <span class="p">{</span> <span class="n">transaction</span> <span class="p">-></span> <span class="c1">// do stuff...</span> <span class="k">val</span> <span class="py">customer</span> <span class="p">=</span> <span class="p">...</span> <span class="n">customer</span><span class="p">.</span><span class="n">save</span><span class="p">();</span> <span class="k">val</span> <span class="py">order</span> <span class="p">=</span> <span class="p">...</span> <span class="n">order</span><span class="p">.</span><span class="n">save</span><span class="p">();</span> <span class="n">transaction</span><span class="p">.</span><span class="n">commit</span><span class="p">()</span> <span class="p">}</span> </pre></div> </div> <h2 id="end">commit(), rollback(), end()</h2> <p> Often with a <em>try with resources</em> block we don't need explicit calls to <code>transaction.rollback()</code> or <code>transaction.end()</code> like the example for <a href="#beginTransaction">beginTransaction()</a> above. </p> <p> <code>rollback()</code> will rollback the transaction and commonly we use that in a catch block. </p> <p> <code>end()</code> will rollback the transaction if it has not already been committed. We primarily use <code>end()</code> in a finally block. </p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="n">Transaction</span> <span class="n">transaction</span> <span class="o">=</span> <span class="n">DB</span><span class="o">.</span><span class="na">beginTransaction</span><span class="o">()</span> <span class="k">try</span> <span class="o">{</span> <span class="c1">// do stuff...</span> <span class="n">Customer</span> <span class="n">customer</span> <span class="o">=</span> <span class="o">...</span> <span class="n">customer</span><span class="o">.</span><span class="na">save</span><span class="o">();</span> <span class="n">Order</span> <span class="n">order</span> <span class="o">=</span> <span class="o">...</span> <span class="n">order</span><span class="o">.</span><span class="na">save</span><span class="o">();</span> <span class="n">transaction</span><span class="o">.</span><span class="na">commit</span><span class="o">();</span> <span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">SomeException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span> <span class="n">transaction</span><span class="o">.</span><span class="na">rollback</span><span class="o">();</span> <span class="o">}</span> <span class="k">finally</span> <span class="o">{</span> <span class="n">transaction</span><span class="o">.</span><span class="na">end</span><span class="o">();</span> <span class="c1">// rollback if not committed</span> <span class="o">}</span> </pre></div> </div> <h2 id="commitAndContinue">commitAndContinue()</h2> <p> Occasionally in larger transactions we get to a point where we would like to commit the changes to this point but then carry on processing with subsequent changes potentially failing. We use <code>transaction.commitAndContinue()</code> for this. </p> <h2 id="setRollbackOnly">setRollbackOnly()</h2> <p> We use <code>transaction.setRollbackOnly()</code> such that a transaction will not commit but only rollback. </p> <p> We can make use of this when some processing has a sort of "preview" mode where we process changes but then do not commit. This can also be useful in some testing scenarios. </p> <h2 id="createTransaction">createTransaction()</h2> <p> <code>database.createTransaction()</code> will create a transaction but it will <em>NOT</em> be put in "thread local scope". We generally use this when we have a transaction that we want to pass between threads. </p> <p> For example: start a transaction, obtain a row lock, if that is successful pass the transaction to a task to execute via a background thread. </p> <p> When we use <code>createTransaction()</code> we must explicitly use the transaction in queries and saving etc. We explicitly specify the transaction with query beans via ... and <em>model.save(transaction)</em> etc. </p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="k">try</span> <span class="o">(</span><span class="n">Transaction</span> <span class="n">transaction</span> <span class="o">=</span> <span class="n">DB</span><span class="o">.</span><span class="na">getDefault</span><span class="o">().</span><span class="na">createTransaction</span><span class="o">())</span> <span class="o">{</span> <span class="o">...</span> <span class="k">var</span> <span class="n">customer</span> <span class="o">=</span> <span class="k">new</span> <span class="n">QCustomer</span><span class="o">(</span><span class="n">transaction</span><span class="o">)</span> <span class="c1">// explicit transaction</span> <span class="o">.</span><span class="na field">name</span><span class="o">.</span><span class="na">eq</span><span class="o">(</span><span class="s">"Rob"</span><span class="o">)</span> <span class="o">.</span><span class="na">findOne</span><span class="o">();</span> <span class="o">...</span> <span class="n">customer</span><span class="o">.</span><span class="na">update</span><span class="o">(</span><span class="n">transaction</span><span class="o">);</span> <span class="c1">// explicit transaction</span> <span class="o">}</span> </pre></div> </div> <h2 id="implicit">Implicit transactions</h2> <p> When no transactions are specified explicitly Ebean will create a transaction to perform the action. </p> <h4>Query - read only transaction</h4> <p> For queries Ebean will look to use a read only transaction. If a <code>Read Only DataSource</code> has be configured Ebean will look to use that by default. </p> <h4>Insert, Update, Delete</h4> <p> For all persist requests like save, insert, update, delete Ebean will create a transaction and perform a <code>COMMIT</code> at the end of the operation. </p> <nav class="next"> <p class="edit-page"> <a href="https://github.com/ebean-orm/website-source/blob/master/docs/transactions/index.html"><i class="fab fa-github"></i> Edit Page</a> </p> <p class="next"> <a href="/docs/transactions/batch" class="btn btn-info">Next: Batch</a> </p> </nav> </article> </div> </div> <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> <script src="/js/site3.js"></script> <script src="/js/search3.js"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=UA-75181644-1"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-75181644-1'); </script> </body> </html>