CINXE.COM
Persist - Ebean ORM
<!DOCTYPE html> <html lang="en"> <head> <title>Persist - Ebean ORM</title> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <script async defer src="https://buttons.github.io/buttons.js"></script> <link rel="shortcut icon" href="/images/favicon.ico" > <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <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/pygments.css" type="text/css" /> <link rel="stylesheet" href="/css/site.css"> </head> <body> <div id="wrap"> <div id="header"> <div class="navbar" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".mobile-nav"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/"> <img src="/images/lg5-21x100.png" height="35"> </a> </div> <div class="collapse navbar-collapse"> <ul class="nav navbar-nav pull-right nav-btn-rhs"> <li ><a href="/"><span class="fas fa-home"></span> Home</a></li> <li class="active"><a href="/docs">Docs</a></li> <li ><a href="/docs/getting-started">Get Started</a></li> <li ><a href="/support">Help</a></li> <li ><a href="/videos">Videos</a></li> <li ><a target="_blank" href="/apidoc/13">ApiDocs</a></li> <li ><a href="/releases">Releases</a></li> <li><a target="_blank" href="https://github.com/ebean-orm/ebean"> <i class="fab fa-github"></i></a></li> </ul> </div> <div class="mobile-nav"> <ul class="nav navbar-nav pull-right nav-btn-rhs"> <li ><a href="/"><span class="fas fa-home"></span> Home</a></li> <li class="active"><a href="/docs">Docs</a></li> <li ><a href="/docs/getting-started">Get Started</a></li> <li ><a href="/support">Help</a></li> <li ><a href="/videos">Videos</a></li> <li ><a target="_blank" href="/apidoc/13">ApiDocs</a></li> <li ><a href="/releases">Releases</a></li> <li><a target="_blank" href="https://github.com/ebean-orm/ebean"> <i class="fab fa-github"></i></a></li> </ul> </div> </div> </div> </div> <div id="main"> <div class="jumbotron mini"> <div class="container"> <h1><a href="/docs/">Documentation</a><span class="sep"> / </span><span class="last">Persist</span></h1> </div> </div> <div class="container doc-index bs-docs-container"> <div class="row"> <div class="col-md-9" role="main"> <form action="https://www.google.com/search" method="get"> <div class="page-inline-search" style="margin-bottom:8px;"> <div class="input-group"> <input name="q" id="searchinput" type="text" class="form-control" 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"> <input type="hidden" name="as_sitesearch" value="ebean.io"> <div class="input-group-btn"> <button class="btn btn-default form-control" type="submit"><i class="glyphicon glyphicon-search"></i></button> </div> </div> <div class="search-results-inline-container" 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="saves">Save</h2> <p> Save will either insert or update the bean depending on its state. </p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="n">Order</span> <span class="n">order</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Order</span><span class="o">();</span> <span class="n">order</span><span class="o">.</span><span class="na">setOrderDate</span><span class="o">(</span><span class="k">new</span> <span class="n">Date</span><span class="o">());</span> <span class="o">...</span> <span class="c1">// insert the order</span> <span class="n">order</span><span class="o">.</span><span class="na">save</span><span class="o">();</span> </pre></div> </div> <p> If the bean was fetched it will be updated... </p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="n">Order</span> <span class="n">order</span> <span class="o">=</span> <span class="n">DB</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">Order</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="mi">42</span><span class="o">);</span> <span class="n">order</span><span class="o">.</span><span class="na">setStatus</span><span class="o">(</span><span class="n">SHIPPED</span><span class="o">);</span> <span class="o">...</span> <span class="c1">// update the order</span> <span class="n">order</span><span class="o">.</span><span class="na">save</span><span class="o">();</span> </pre></div> </div> <p> Save and Delete will CASCADE based on the CascadeType specificed on the associated @OneToMany, @OneToOne etc annotation. </p> <p> By default save and delete will not cascade so you need to specify a cascade type (such as the one on details below) for save() or delete() to cascade. </p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="o">...</span> <span class="nd">@Entity</span> <span class="nd">@Table</span><span class="o">(</span><span class="nx">name</span><span class="o">=</span><span class="s">"orders"</span><span class="o">)</span> <span class="kd">public</span> <span class="kd">class</span> <span class="nc">Order</span> <span class="o">{</span> <span class="o">...</span> <span class="nd">@ManyToOne</span> <span class="c1">// no cascading</span> <span class="n">Customer</span> <span class="n">customer</span><span class="o">;</span> <span class="nd">@OneToMany</span><span class="o">(</span><span class="nx">cascade</span><span class="o">=</span><span class="nx">CascadeType</span><span class="o">.</span><span class="na">ALL</span><span class="o">)</span> <span class="c1">// save and delete cascaded</span> <span class="n">List</span><span class="o"><</span><span class="n">OrderDetail</span><span class="o">></span> <span class="n">details</span><span class="o">;</span> <span class="o">...</span> </pre></div> </div> <p> Note the <em>@OneToMany(cascade=CascadeType.ALL)</em> on the details property. This means save() and delete() will both casade from order to its order details. </p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="o">...</span> <span class="c1">// save the order ... will cascade also saving the order details</span> <span class="n">DB</span><span class="o">.</span><span class="na">save</span><span class="o">(</span><span class="n">order</span><span class="o">);</span> </pre></div> </div> <h2 id="deletes">Delete</h2> <p> Delete is very similar to save. Just call DB.delete(); </p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="o">...</span> <span class="n">Order</span> <span class="n">order</span> <span class="o">=</span> <span class="n">DB</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">Order</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="mi">12</span><span class="o">);</span> <span class="c1">// delete the order</span> <span class="c1">// ... this will cascade also deleting the order details</span> <span class="c1">// ... with either CascadeType.ALL or CascadeType.REMOVE</span> <span class="n">DB</span><span class="o">.</span><span class="na">delete</span><span class="o">(</span><span class="n">order</span><span class="o">);</span> </pre></div> </div> <h2 id="cascading">Cascading</h2> <p>The mapping annotations @ManyToOne, @OneToMany, @OneToOne and @ManyToMany provide a cascade attribute which is used to control whether saves and deletes are cascaded.</p> <p>The default is to not cascade a save or delete (as per JPA spec).</p> <p>The example below shows the Order entity bean with its mapping annotations. If you save an Order the details will be saved as well but the associated customer will not be saved as there is no cascade atttribute and the default is to not cascade.</p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="o">...</span> <span class="nd">@Entity</span> <span class="nd">@Table</span><span class="o">(</span><span class="nx">name</span><span class="o">=</span><span class="s">"orders"</span><span class="o">)</span> <span class="kd">public</span> <span class="kd">class</span> <span class="nc">Order</span> <span class="o">{</span> <span class="o">...</span> <span class="nd">@ManyToOne</span> <span class="c1">// no cascading</span> <span class="n">Customer</span> <span class="n">customer</span><span class="o">;</span> <span class="nd">@OneToMany</span><span class="o">(</span><span class="nx">cascade</span><span class="o">=</span><span class="nx">CascadeType</span><span class="o">.</span><span class="na">ALL</span><span class="o">)</span> <span class="c1">// save and delete cascaded</span> <span class="n">List</span><span class="o"><</span><span class="n">OrderDetail</span><span class="o">></span> <span class="n">details</span><span class="o">;</span> </pre></div> </div> <h2 id="bulkupdate">Bulk updates</h2> <p>Update provides a way on issuing a insert, update or delete statement.</p> <p> This is useful for updating or deleting multiple rows (or a single row) with a single statement (often described as a "bulk" update).</p> <p>This is also useful if you want to perform an update or delete without having to execute a query first. This is a typical approach for performing an update in a stateless web application.</p> <p>The statement can be provided in as raw DML with the table names and column names or in a 'logical' form where entity name is used in place of the table name and property names are used in place of column names.</p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="c1">// orm bulk delete use bean name and bean properties</span> <span class="n">DB</span><span class="o">.</span><span class="na">createUpdate</span><span class="o">(</span><span class="n">OrderDetail</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="s">"delete from orderDetail"</span><span class="o">).</span><span class="na">execute</span><span class="o">();</span> <span class="c1">// sql bulk update uses table and column names</span> <span class="n">DB</span><span class="o">.</span><span class="na">sqlUpdate</span><span class="o">(</span><span class="s">"delete from country"</span><span class="o">).</span><span class="na">execute</span><span class="o">();</span> </pre></div> </div>` <h2 id="bulksqlupdate">Bulk SQL updates</h2> <p>In similar fashion to <a href="#sqlquery">SqlQuery</a> you can specify a SQL INSERT, UPDATE or DELETE statement with named or positioned parameters.</p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="n">String</span> <span class="n">dml</span> <span class="o">=</span> <span class="s">"update b_bug set title=:title where id = :id"</span><span class="o">;</span> <span class="kt">int</span> <span class="n">rows</span> <span class="o">=</span> <span class="n">DB</span><span class="o">.</span><span class="na">sqlUpdate</span><span class="o">(</span><span class="n">dml</span><span class="o">)</span> <span class="o">.</span><span class="na">setParameter</span><span class="o">(</span><span class="s">"title"</span><span class="o">,</span> <span class="s">"Updated Again"</span><span class="o">)</span> <span class="o">.</span><span class="na">setParameter</span><span class="o">(</span><span class="s">"id"</span><span class="o">,</span> <span class="mi">1</span><span class="o">)</span> <span class="o">.</span><span class="na">execute</span><span class="o">();</span> </pre></div> </div> <h2 id="callablesql">CallableSql</h2> <p>CallableSql provides a way to call a database stored procedure.</p> <div class="syntax java"><div class="highlight"><pre><span></span><span class="n">String</span> <span class="n">sql</span> <span class="o">=</span> <span class="s">"{call sp_order_mod(?,?)}"</span><span class="o">;</span> <span class="n">CallableSql</span> <span class="n">cs</span> <span class="o">=</span> <span class="n">DB</span><span class="o">.</span><span class="na">createCallableSql</span><span class="o">(</span><span class="n">sql</span><span class="o">);</span> <span class="n">cs</span><span class="o">.</span><span class="na">setParameter</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="s">"turbo"</span><span class="o">);</span> <span class="n">cs</span><span class="o">.</span><span class="na">registerOut</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="n">Types</span><span class="o">.</span><span class="na">INTEGER</span><span class="o">);</span> <span class="n">DB</span><span class="o">.</span><span class="na">execute</span><span class="o">(</span><span class="n">cs</span><span class="o">);</span> <span class="c1">// read the out parameter</span> <span class="n">Integer</span> <span class="n">returnValue</span> <span class="o">=</span> <span class="o">(</span><span class="n">Integer</span><span class="o">)</span> <span class="n">cs</span><span class="o">.</span><span class="na">getObject</span><span class="o">(</span><span class="mi">2</span><span class="o">);</span> </pre></div> </div> <p>You can extend CallableSql and you can also get the java.sql.Connection from a Transaction and use raw JDBC API to call a stored procedure.</p> <h2 id="rawjdbc">Raw JDBC</h2> <p>You can't always predict when your application requirements can't be met with the features in Ebean. It is nice to know you can easily use raw JDBC if and when you need to.</p> <p>The java.sql.Connection object can be returned from a transaction, and with that you can perform any raw JDBC calls you like.</p> <p>This may be useful for Savepoints, advanced Clob/Blob use or advanced stored procedure calls (if CallableSql doesn't do the business for you).</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="n">Connection</span> <span class="n">connection</span> <span class="o">=</span> <span class="n">transaction</span><span class="o">.</span><span class="na">getConnection</span><span class="o">();</span> <span class="c1">// use raw JDBC</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> <h2 id="batch_processing">JDBC Batch</h2> <p> Ebean provides support for JDBC batch processing. Batch processing groups related SQL statements into a batch and submits them with one call to the database. </p> <p> Batch settings can be configured through application.properties or through DatabaseConfig, and can be overridden per transaction. </p> <p> You can set the batch mode for the entity being saved through setBatch() and for its child collections through setCascadeBatch(). </p> <p> ...(under construction)... need to provide better guidance on how to determine batch mode, child batch mode, and batch size </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">database</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">// turn of cascade persist</span> <span class="n">transaction</span><span class="o">.</span><span class="na">setCascadePersist</span><span class="o">(</span><span class="kc">false</span><span class="o">);</span> <span class="c1">// control the jdbc batch mode and size</span> <span class="c1">// transaction.setBatchMode(true); // equivalent to transaction.setBatch(PersistBatch.ALL);</span> <span class="c1">// transaction.setBatchMode(false); // equivalent to transaction.setBatch(PersistBatch.NONE);</span> <span class="n">transaction</span><span class="o">.</span><span class="na">setBatch</span><span class="o">(</span><span class="n">PersistBatch</span><span class="o">.</span><span class="na">ALL</span><span class="o">);</span> <span class="c1">// PersistBatch: NONE, INSERT, ALL</span> <span class="n">transaction</span><span class="o">.</span><span class="na">setCascadeBatch</span><span class="o">(</span><span class="n">PersistBatch</span><span class="o">.</span><span class="na">INSERT</span><span class="o">);</span> <span class="c1">// PersistBatch: NONE, INSERT, ALL</span> <span class="n">transaction</span><span class="o">.</span><span class="na">setBatchSize</span><span class="o">(</span><span class="mi">30</span><span class="o">);</span> <span class="c1">// for a large batch insert if you want to skip</span> <span class="c1">// getting the generated keys</span> <span class="n">transaction</span><span class="o">.</span><span class="na">setGetGeneratedKeys</span><span class="o">(</span><span class="kc">false</span><span class="o">);</span> <span class="c1">// for batch processing via raw SQL you can inform</span> <span class="c1">// Ebean what tables were modified so that it can</span> <span class="c1">// clear the appropriate L2 caches</span> <span class="n">String</span> <span class="n">tableName</span> <span class="o">=</span> <span class="s">"customer"</span><span class="o">;</span> <span class="kt">boolean</span> <span class="n">inserts</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span> <span class="kt">boolean</span> <span class="n">upates</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span> <span class="kt">boolean</span> <span class="n">deletes</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span> <span class="n">transaction</span><span class="o">.</span><span class="na">addModification</span><span class="o">(</span><span class="n">tableName</span><span class="o">,</span> <span class="n">inserts</span><span class="o">,</span> <span class="n">updates</span><span class="o">,</span> <span class="n">deletes</span><span class="o">);</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="o">}</span> </pre></div> </div> example using @Transactional <div class="syntax java"><div class="highlight"><pre><span></span><span class="nd">@Transactional</span><span class="o">(</span><span class="nx">batchSize</span> <span class="o">=</span> <span class="mi">50</span><span class="o">)</span> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">goodStuff</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">customer</span><span class="o">.</span><span class="na">save</span><span class="o">()</span> <span class="o">}</span> </pre></div> </div> <div class="next pull-right"> <a href="/docs/transactions" class="btn btn-info">Next: Transactions</a> </div> </div> <div class="col-md-3" role="complementary"> <nav class="bs-docs-sidebar hidden-print hidden-xs hidden-sm"> <ul class="nav bs-docs-sidenav"> <li class="active"> <a href="/docs/persist">Persist</a> <ul class="nav"> <li><a href="#saves">Save</a></li> <li><a href="#deletes">Delete</a></li> <li><a href="#cascading">Cascade</a></li> <li><a href="#bulkupdate">Bulk updates</a></li> <li><a href="#bulksqlupdate">Bulk SQL updates</a></li> <li><a href="#callablesql">CallableSql</a></li> <li><a href="#rawjdbc">Raw JDBC</a></li> <li><a href="#batch_processing">JDBC Batch</a></li> </ul> </li> </ul> </nav> </div> </div> </div> </div> </div> <footer id="footer"> <div class="doc-footer"> <ul class="doc-footer-links"> <li><a href="/">Ebean ORM</a></li> <li> | </li> <li><a href="http://avaje-metric.github.io">Metrics</a></li> </ul> </div> </footer> <script type="text/javascript"> var categoryNames = {}; </script> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <script src="/js/bootstrap.min.js"></script> <script src="/js/jquery.easing.min.js"></script> <script src="/js/jquery.storageapi.min.js"></script> <script src="/js/ebean-site.js"></script> <script src="/js/extra.js"></script> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-75181644-1', 'auto'); ga('send', 'pageview'); </script> </body> </html>