CINXE.COM
Kotlin | Ebean
<!doctype html> <html lang="en"> <head> <title>Kotlin | 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">Kotlin</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 "> <a href="/docs/transactions">Transactions</a> </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 active"> <a class="active" href="/docs/kotlin">Kotlin</a> <ul class="nav nav-scroll"> <li > <a href="#constructors">Constructors</a> </li> <li > <a href="#non-nullable">Non-nullable types</a> </li> <li > <a href="#mapped-superclass">MappedSuperclass</a> </li> <li > <a href="#oneToMany">@OneToMany</a> </li> </ul> </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="constructors">Constructors</h2> <p> Ebean does not require a default constructor. We should use constructors to supply the required / non-nullable properties when creating entity bean instances. </p> <p> For example, if a Customer entity bean requires a name property we can have that in the constructor and use a Kotlin non-nullable type. </p> <div class="syntax kotlin"><div class="highlight"><pre><span></span><span class="p">...</span> <span class="nd">@Entity</span> <span class="k">class</span> <span class="nc">Customer</span><span class="p">(</span><span class="n">name</span> <span class="p">:</span> <span class="n">String</span><span class="p">)</span> <span class="p">:</span> <span class="n">BaseModel</span><span class="p">()</span> <span class="p">{</span> <span class="nd">@Length</span><span class="p">(</span><span class="m">100</span><span class="p">)</span> <span class="k">var</span> <span class="py">name</span><span class="p">:</span> <span class="n">String</span> <span class="p">=</span> <span class="n">name</span> <span class="c1">// Kotlin non-nullable type</span> <span class="p">}</span> </pre></div> </div> <p> The <em>suggested</em> constructor style to use with Kotlin is like the above with the constructor parameter assigned to the property. The reason for this is that with entity bean properties we often have mapping annotations (<code>@Length</code> etc) and it can be easier / clearer to not have those as part of the constructor (where there are more targets for the annotations - method, field, parameter etc). </p> <h2 id="non-nullable">Non-nullable types</h2> <p> Ebean is aware of Kotlin non nullable types and automatically treats them as <code>@NotNull</code>. We don't need to specify <code>@NotNull</code> or <code>@Column(nullable=false)</code> or <code>@ManyToOne(optional=false)</code> when the property is a Kotlin non nullable type. </p> <h2 id="mapped-superclass">MappedSuperclass</h2> <p> It is common to have a mapped superclass that extends <code>io.ebean.Model</code> and has <code>@WhenCreated</code> and <code>@WhenModified</code> like below: </p> <div class="syntax kotlin"><div class="highlight"><pre><span></span><span class="nd">@MappedSuperclass</span> <span class="k">abstract</span> <span class="k">class</span> <span class="nc">BaseModel</span> <span class="p">:</span> <span class="n">Model</span><span class="p">()</span> <span class="p">{</span> <span class="nd">@Id</span> <span class="k">var</span> <span class="py">id</span><span class="p">:</span> <span class="n">Long</span> <span class="p">=</span> <span class="m">0</span> <span class="nd">@Version</span> <span class="k">var</span> <span class="py">version</span><span class="p">:</span> <span class="n">Long</span> <span class="p">=</span> <span class="m">0</span> <span class="nd">@WhenCreated</span> <span class="k">lateinit</span> <span class="k">var</span> <span class="py">whenCreated</span><span class="p">:</span> <span class="n">Instant</span> <span class="nd">@WhenModified</span> <span class="k">lateinit</span> <span class="k">var</span> <span class="py">whenModified</span><span class="p">:</span> <span class="n">Instant</span> <span class="p">}</span> </pre></div> </div> <p> It is ok to use <code>lateinit</code> for the whenCreated and whenModified properties and have them as nullable types. </p> <p> It is good to use non nullable <code>Int = 0</code> and <code>Long = 0</code> for <code>@Id</code> properties like the example above (JVM primitive int and long). </p> <h2 id="oneToMany">@OneToMany</h2> <p> For collection types <code>@OneToMany</code> and <code>@ManyToMany</code> it is good to use non nullable mutable lists and initialise then with <code>mutableListOf()</code>. Ebean enhancement will optimise this and collection types will only be initialised when needed (so it's good to model it as a Kotlin non nullable collection type). </p> <div class="syntax kotlin"><div class="highlight"><pre><span></span><span class="nd">@Entity</span> <span class="nd">@Table</span><span class="p">(</span><span class="nx">name</span> <span class="p">=</span> <span class="s">"orders"</span><span class="p">)</span> <span class="k">class</span> <span class="nc">Order</span><span class="p">(</span><span class="n">customer</span><span class="p">:</span> <span class="n">Customer</span><span class="p">)</span> <span class="p">:</span> <span class="n">BaseModel</span><span class="p">()</span> <span class="p">{</span> <span class="p">...</span> <span class="nd">@OneToMany</span><span class="p">(</span><span class="nx">mappedBy</span> <span class="p">=</span> <span class="s">"order"</span><span class="p">,</span> <span class="nx">cascade</span> <span class="p">=</span> <span class="p">[</span><span class="nx">CascadeType</span><span class="p">.</span><span class="nx">PERSIST</span><span class="p">])</span> <span class="k">var</span> <span class="py">details</span><span class="p">:</span> <span class="n">MutableList</span><span class="p"><</span><span class="n">OrderDetail</span><span class="p">></span> <span class="p">=</span> <span class="n">mutableListOf</span><span class="p">()</span> <span class="p">}</span> </pre></div> </div> </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>