|
| 1 | +<!DOCTYPE html> |
| 2 | +<html> |
| 3 | +<head> |
| 4 | + <meta charset='utf-8'> |
| 5 | + <meta http-equiv="X-UA-Compatible" content="chrome=1"> |
| 6 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 7 | + <!--link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"--> |
| 8 | + <link rel="stylesheet" href="/gfx/bootstrap.min.css"> |
| 9 | + <link rel="stylesheet" href="/gfx/main.css"> |
| 10 | + <link rel="stylesheet" href="/gfx/code.css"> |
| 11 | + <title>2.8.0 Release Notes</title> |
| 12 | +</head> |
| 13 | +<body class="page"> |
| 14 | +<!-- Google Tag Manager --> |
| 15 | +<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-PMJSKV" |
| 16 | +height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> |
| 17 | +<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': |
| 18 | +new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], |
| 19 | +j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= |
| 20 | +'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); |
| 21 | +})(window,document,'script','dataLayer','GTM-PMJSKV');</script> |
| 22 | +<!-- End Google Tag Manager --> |
| 23 | + |
| 24 | +<header> |
| 25 | + <div class="container"> |
| 26 | + <a href="/">Immutables</a> ← |
| 27 | + |
| 28 | + <h1>2.8.0 Release Notes <iframe src="https://ghbtns.com/github-btn.html?user=immutables&repo=immutables&type=star&count=true&size=large" frameborder="0" scrolling="0" width="160px" height="30px"></iframe> |
| 29 | +</h1> |
| 30 | + </div> |
| 31 | +</header> |
| 32 | +<aside id="toc"></aside> |
| 33 | +<section class="documentation"> |
| 34 | + <h2>Overview</h2> |
| 35 | + |
| 36 | +<p>Criteria API: combine power of immutable objects with the flexibility of querying them </p> |
| 37 | + |
| 38 | +<p><a href="https://immutables.github.io/">Immutables</a> team is pleased to announce Immutables 2.8.0 release. </p> |
| 39 | + |
| 40 | +<p>Major focus of this release was <a href="https://immutables.github.io/criteria.html">Criteria API</a> which enables |
| 41 | +users to generate model-specific query DSL. Generated class (along with criteria runtime) allows accessing different backends in a unified, fluent and type-safe manner.</p> |
| 42 | + |
| 43 | +<p>Benefits over raw driver API usage or string based abstractions (DSLs) are:</p> |
| 44 | + |
| 45 | +<ol> |
| 46 | +<li>Compile-time checking and type safety allows for much fewer mistakes </li> |
| 47 | +<li>IDE auto-completion guides through the choice of fields and operators</li> |
| 48 | +<li>Best in class readability due to drastically reduced number of parentheses and specially designed <a href="http://en.wikipedia.org/wiki/Disjunctive_normal_form">DNF</a> approach</li> |
| 49 | +<li>Easier model refactoring </li> |
| 50 | +</ol> |
| 51 | + |
| 52 | +<p>Benefits over existing frameworks like <a href="https://spring.io/projects/spring-data">Spring Data</a>, <a href="https://morphia.dev/">Morphia</a>, <a href="http://www.querydsl.com/">QueryDSL</a> or <a href="https://www.jooq.org/">jOOQ</a> are:</p> |
| 53 | + |
| 54 | +<ol> |
| 55 | +<li>Derive immutable implementation, query DSL, repository and more from a single definition</li> |
| 56 | +<li>Pluggable Sync / Async / Reactive execution models </li> |
| 57 | +<li>Pluggable backend implementations</li> |
| 58 | +<li>Generated or custom Repositories (aka DAOs) can be controlled to generate reading / writing or <a href="https://docs.mongodb.com/manual/changeStreams/">watching</a> operations on entities</li> |
| 59 | +</ol> |
| 60 | + |
| 61 | +<h3>Querying</h3> |
| 62 | + |
| 63 | +<p>Define your model ...</p> |
| 64 | +<div class="highlight"><pre><code class="language-java" data-lang="java"><span></span><span class="nd">@Value.Immutable</span> |
| 65 | +<span class="nd">@Criteria</span> <span class="c1">// generate query DSL</span> |
| 66 | +<span class="nd">@Criteria.Repository</span> <span class="c1">// generate repository for this model</span> |
| 67 | +<span class="kd">interface</span> <span class="nc">Person</span> <span class="o">{</span> |
| 68 | + <span class="n">String</span> <span class="nf">fullName</span><span class="o">();</span> |
| 69 | + <span class="kt">int</span> <span class="nf">age</span><span class="o">();</span> |
| 70 | + <span class="n">Optional</span><span class="o"><</span><span class="n">String</span><span class="o">></span> <span class="nf">nickName</span><span class="o">();</span> |
| 71 | + <span class="n">List</span><span class="o"><</span><span class="n">Pet</span><span class="o">></span> <span class="nf">pets</span><span class="o">();</span> |
| 72 | + <span class="n">Optional</span><span class="o"><</span><span class="n">Friend</span><span class="o">></span> <span class="nf">bestFriend</span><span class="o">();</span> |
| 73 | + <span class="c1">// ... </span> |
| 74 | +<span class="o">}</span> |
| 75 | +</code></pre></div> |
| 76 | +<p>... and start querying it with Criteria API</p> |
| 77 | +<div class="highlight"><pre><code class="language-java" data-lang="java"><span></span><span class="c1">// basic query by ID</span> |
| 78 | +<span class="n">PersonCriteria</span><span class="o">.</span><span class="na">person</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">in</span><span class="o">(</span><span class="s">"id1"</span><span class="o">,</span> <span class="s">"id2"</span><span class="o">,</span> <span class="s">"id3"</span><span class="o">);</span> |
| 79 | +<span class="n">PersonCriteria</span><span class="o">.</span><span class="na">person</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">notIn</span><span class="o">(</span><span class="s">"bad_id"</span><span class="o">);</span> |
| 80 | + |
| 81 | +<span class="c1">// more complex query on Strings, Comparables, Optionals and other nested Criterias</span> |
| 82 | +<span class="n">person</span> |
| 83 | + <span class="o">.</span><span class="na">fullName</span><span class="o">.</span><span class="na">is</span><span class="o">(</span><span class="s">"John"</span><span class="o">)</span> <span class="c1">// basic equal</span> |
| 84 | + <span class="o">.</span><span class="na">fullName</span><span class="o">.</span><span class="na">isNot</span><span class="o">(</span><span class="s">"Mary"</span><span class="o">)</span> <span class="c1">// not equal</span> |
| 85 | + <span class="o">.</span><span class="na">fullName</span><span class="o">.</span><span class="na">endsWith</span><span class="o">(</span><span class="s">"Smith"</span><span class="o">)</span> <span class="c1">// string condition</span> |
| 86 | + <span class="o">.</span><span class="na">fullName</span><span class="o">.</span><span class="na">is</span><span class="o">(</span><span class="mf">3.1415D</span><span class="o">)</span> <span class="c1">// ERROR! will not compile since fullName is String (not double)</span> |
| 87 | + <span class="o">.</span><span class="na">nickName</span><span class="o">.</span><span class="na">isPresent</span><span class="o">()</span> <span class="c1">// for Optional attribute</span> |
| 88 | + <span class="o">.</span><span class="na">nickName</span><span class="o">.</span><span class="na">startsWith</span><span class="o">(</span><span class="s">"Adam"</span><span class="o">)</span> <span class="c1">// special matcher Optional<String> which is intersetion type between OptionalMatcher and StringMatcher</span> |
| 89 | + <span class="o">.</span><span class="na">pets</span><span class="o">.</span><span class="na">notEmpty</span><span class="o">()</span> <span class="c1">// condition on an Iterable</span> |
| 90 | + <span class="o">.</span><span class="na">active</span><span class="o">.</span><span class="na">isTrue</span><span class="o">()</span> <span class="c1">// boolean</span> |
| 91 | + <span class="o">.</span><span class="na">or</span><span class="o">()</span> <span class="c1">// disjunction (equivalent to logical OR)</span> |
| 92 | + <span class="o">.</span><span class="na">age</span><span class="o">.</span><span class="na">atLeast</span><span class="o">(</span><span class="mi">21</span><span class="o">)</span> <span class="c1">// comparable attribute</span> |
| 93 | + <span class="o">.</span><span class="na">or</span><span class="o">()</span> |
| 94 | + <span class="o">.</span><span class="na">not</span><span class="o">(</span><span class="n">p</span> <span class="o">-></span> <span class="n">p</span><span class="o">.</span><span class="na">nickName</span><span class="o">.</span><span class="na">hasLength</span><span class="o">(</span><span class="mi">4</span><span class="o">));</span> <span class="c1">// negation on a Optional<String> attribute</span> |
| 95 | + <span class="o">.</span><span class="na">bestFriend</span><span class="o">.</span><span class="na">value</span><span class="o">().</span><span class="na">hobby</span><span class="o">.</span><span class="na">endsWith</span><span class="o">(</span><span class="s">"ing"</span><span class="o">)</span> <span class="c1">// chaining criterias on other entities like Optional<Friend> </span> |
| 96 | +</code></pre></div> |
| 97 | +<p>You will notice that there are no <code>and</code> statements (conjunctions) that is because criteria uses |
| 98 | +<a href="https://en.wikipedia.org/wiki/Disjunctive_normal_form">Disjunctive Normal Form</a> (in short DNF) by default. Statements are |
| 99 | +combined using logical <code>and</code> unless disjunction <code>or()</code> is explicitly used. One can still build complex logical expressions |
| 100 | +by composing criterias using <code>and</code>/ <code>or</code> functions.</p> |
| 101 | + |
| 102 | +<h4>ordering / limit / offset</h4> |
| 103 | + |
| 104 | +<p>Typical <code>ORDER BY</code> / <code>LIMIT</code> / <code>OFFSET</code> operations are part of API</p> |
| 105 | +<div class="highlight"><pre><code class="language-java" data-lang="java"><span></span><span class="c1">// query datasource and return reactive type: Flowable</span> |
| 106 | +<span class="n">List</span><span class="o"><</span><span class="n">Person</span><span class="o">></span> <span class="n">persons</span> <span class="o">=</span> <span class="n">repository</span> |
| 107 | + <span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">person</span><span class="o">.</span><span class="na">age</span><span class="o">.</span><span class="na">atLeast</span><span class="o">(</span><span class="mi">33</span><span class="o">))</span> |
| 108 | + <span class="o">.</span><span class="na">orderBy</span><span class="o">(</span><span class="n">person</span><span class="o">.</span><span class="na">fullName</span><span class="o">.</span><span class="na">asc</span><span class="o">())</span> |
| 109 | + <span class="o">.</span><span class="na">offset</span><span class="o">(</span><span class="mi">20</span><span class="o">)</span> |
| 110 | + <span class="o">.</span><span class="na">limit</span><span class="o">(</span><span class="mi">10</span><span class="o">)</span> |
| 111 | + <span class="o">.</span><span class="na">fetch</span><span class="o">();</span> |
| 112 | +</code></pre></div> |
| 113 | +<h4>Projections and Aggregations</h4> |
| 114 | + |
| 115 | +<p>Projections and Aggregations (like <code>count</code> / <code>min</code> / <code>max</code> / <code>sum</code> / <code>avg</code> ) are also supported.</p> |
| 116 | +<div class="highlight"><pre><code class="language-java" data-lang="java"><span></span><span class="n">List</span><span class="o"><</span><span class="n">String</span><span class="o">></span> <span class="n">list</span> <span class="o">=</span> <span class="n">repository</span><span class="o">.</span><span class="na">findAll</span><span class="o">()</span> |
| 117 | + <span class="o">.</span><span class="na">orderBy</span><span class="o">(</span><span class="n">person</span><span class="o">.</span><span class="na">nickName</span><span class="o">.</span><span class="na">desc</span><span class="o">())</span> |
| 118 | + <span class="o">.</span><span class="na">groupBy</span><span class="o">(</span><span class="n">person</span><span class="o">.</span><span class="na">nickName</span><span class="o">)</span> |
| 119 | + <span class="o">.</span><span class="na">select</span><span class="o">(</span><span class="n">person</span><span class="o">.</span><span class="na">nickName</span><span class="o">,</span> <span class="n">person</span><span class="o">.</span><span class="na">age</span><span class="o">.</span><span class="na">max</span><span class="o">(),</span> <span class="n">person</span><span class="o">.</span><span class="na">age</span><span class="o">.</span><span class="na">min</span><span class="o">(),</span> <span class="n">person</span><span class="o">.</span><span class="na">age</span><span class="o">.</span><span class="na">count</span><span class="o">(),</span> <span class="n">person</span><span class="o">.</span><span class="na">age</span><span class="o">.</span><span class="na">sum</span><span class="o">())</span> |
| 120 | + <span class="o">.</span><span class="na">map</span><span class="o">((</span><span class="n">nickName</span><span class="o">,</span> <span class="n">max</span><span class="o">,</span> <span class="n">min</span><span class="o">,</span> <span class="n">count</span><span class="o">,</span> <span class="n">sum</span><span class="o">)</span> <span class="o">-></span> <span class="o">(</span><span class="s">"nick="</span> <span class="o">+</span> <span class="n">nickName</span><span class="o">.</span><span class="na">orElse</span><span class="o">(</span><span class="kc">null</span><span class="o">)</span> <span class="o">+</span> <span class="s">" diff="</span> <span class="o">+</span> <span class="o">(</span><span class="n">max</span> <span class="o">-</span> <span class="n">min</span><span class="o">)</span> <span class="o">+</span> <span class="s">" count="</span> <span class="o">+</span> <span class="n">count</span> <span class="o">+</span> <span class="s">" sum="</span> <span class="o">+</span> <span class="n">sum</span><span class="o">)))</span> <span class="c1">// type-safe projections</span> |
| 121 | + <span class="o">.</span><span class="na">fetch</span><span class="o">();</span> |
| 122 | +</code></pre></div> |
| 123 | +<h3>Backends</h3> |
| 124 | + |
| 125 | +<p>Backend is the bridge between criteria abstraction and native driver API (or queries). Instantiate a backend and attach it to a repository. It can then be used by your application. |
| 126 | +Note that backends can be exchanged without impacting existing repository usages.</p> |
| 127 | +<div class="highlight"><pre><code class="language-java" data-lang="java"><span></span><span class="c1">// pluggable backends</span> |
| 128 | +<span class="n">Backend</span> <span class="n">backend</span> <span class="o">=</span> <span class="k">new</span> <span class="n">MongoBackend</span><span class="o">(...);</span> <span class="c1">// can be different backend (elastic, geode etc.)</span> |
| 129 | +<span class="n">PersonRepository</span> <span class="n">repository</span> <span class="o">=</span> <span class="k">new</span> <span class="n">PersonRepository</span><span class="o">(</span><span class="n">backend</span><span class="o">);</span> |
| 130 | +</code></pre></div> |
| 131 | +<p>Out of the box, Criteria supports the following backends (you can also integrate your own):</p> |
| 132 | + |
| 133 | +<ol> |
| 134 | +<li>In-Memory Backend. Simple hashmap implementation on the top of <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentMap.html">ConcurrentMap</a></li> |
| 135 | +<li><a href="https://www.elastic.co/">Elastic Search</a></li> |
| 136 | +<li><a href="https://www.mongodb.com/">MongoDB</a></li> |
| 137 | +<li><a href="https://geode.apache.org/">Apache Geode</a></li> |
| 138 | +<li>Bring Your Own Backend (BYOB)</li> |
| 139 | +</ol> |
| 140 | + |
| 141 | +<h3>Sync / Async / Reactive execution models</h3> |
| 142 | + |
| 143 | +<p>Flexible stream processing models adaptable to various usecases:</p> |
| 144 | + |
| 145 | +<ul> |
| 146 | +<li>Synchronous. Returning List / Optional / void / etc.</li> |
| 147 | +<li>Asyncronous. Returning <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html">CompletionStage</a></li> |
| 148 | +<li>Reactive streams. Returning <a href="https://www.reactive-streams.org/reactive-streams-1.0.2-javadoc/org/reactivestreams/Publisher.html">Publisher</a></li> |
| 149 | +<li><a href="https://github.com/ReactiveX/RxJava">RxJava</a>. Returning <a href="http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable.html">Flowable</a> / <a href="http://reactivex.io/RxJava/javadoc/io/reactivex/Single.html">Single</a> / <a href="http://reactivex.io/RxJava/javadoc/io/reactivex/Maybe.html">Maybe</a>. </li> |
| 150 | +<li><a href="https://projectreactor.io">Project Reactor</a>. Returning <a href="https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html">Flux</a> / <a href="https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html">Mono</a>. </li> |
| 151 | +</ul> |
| 152 | +<div class="highlight"><pre><code class="language-java" data-lang="java"><span></span><span class="c1">// one of RxJavaReadable/ SyncReadable/ AsyncReadable etc.</span> |
| 153 | +<span class="nd">@Criteria.Repository</span><span class="o">(</span><span class="n">facets</span><span class="o">=</span><span class="n">RxJavaReadable</span><span class="o">.</span><span class="na">class</span><span class="o">)</span> |
| 154 | +<span class="kd">interface</span> <span class="nc">Person</span> <span class="o">{}</span> |
| 155 | + |
| 156 | +<span class="c1">// return rxjava Flowable type</span> |
| 157 | +<span class="n">Flowable</span><span class="o"><</span><span class="n">Person</span><span class="o">></span> <span class="n">result</span> <span class="o">=</span> <span class="n">repository</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">person</span><span class="o">.</span><span class="na">active</span><span class="o">.</span><span class="na">isTrue</span><span class="o">()).</span><span class="na">fetch</span><span class="o">();</span> |
| 158 | +</code></pre></div> |
| 159 | +<h3>Note on existing Mongo Repositories</h3> |
| 160 | + |
| 161 | +<p>While we don't yet deprecate existing <a href="https://immutables.github.io/mongo.html">mongo repositories</a>, new and current users are encouraged to consider criteria API |
| 162 | +as a better alternative.</p> |
| 163 | + |
| 164 | +<p>Please follow <a href="https://immutables.github.io/criteria.html">official guide</a> for more information.</p> |
| 165 | + |
| 166 | +</section> |
| 167 | +<footer class="jumbotron"> |
| 168 | + <div class="container"> |
| 169 | + <h2>Guides</h2> |
| 170 | + |
| 171 | +<ul> |
| 172 | +<li><a href="/getstarted.html">Get started!</a></li> |
| 173 | +<li><a href="/intro.html">Inception</a></li> |
| 174 | +<li><a href="/immutable.html">Immutable objects</a></li> |
| 175 | +<li><a href="/factory.html">Factory builders</a></li> |
| 176 | +<li><a href="/functional.html">Functions and Predicates (for Java 7)</a></li> |
| 177 | +<li><a href="/style.html">Style customization</a></li> |
| 178 | +<li><a href="/json.html">JSON serialization</a></li> |
| 179 | +<li><a href="/criteria.html">Criteria</a></li> |
| 180 | +<li><a href="/mongo.html">MongoDB repositories</a></li> |
| 181 | +<li><a href="/encoding.html">Encoding: Customizing attributes and builders (experimental)</a></li> |
| 182 | +<li><a href="/apt.html">Using annotation processor in IDE</a></li> |
| 183 | +</ul> |
| 184 | + |
| 185 | +<h2>Get involved</h2> |
| 186 | + |
| 187 | +<ul> |
| 188 | +<li>Clone source repository, contribute bug reports and fixes on <a href="https://github.com/immutables/immutables">GitHub immutables/immutables</a></li> |
| 189 | +<li>Issue reports, questions and feedback is welcome on issue tracker <a href="https://github.com/immutables/immutables/issues">GitHub immutables/immutables/issues</a></li> |
| 190 | +<li>News and announcements on twitter <a href="https://twitter.com/ImmutablesOrg">@ImmutablesOrg</a></li> |
| 191 | +</ul> |
| 192 | + |
| 193 | +<p><a href="/license.html">Apache License 2.0</a></p> |
| 194 | + |
| 195 | + <!--<div><h2>Posts</h2> |
| 196 | + <ul> |
| 197 | + |
| 198 | + </ul> |
| 199 | + </div>--> |
| 200 | + </div> |
| 201 | +</footer> |
| 202 | +<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script> |
| 203 | +<script defer src="/gfx/jquery.toc.min.js"></script> |
| 204 | +<script> |
| 205 | +$(function() { |
| 206 | + $('#toc').toc({ |
| 207 | + container: '.documentation', |
| 208 | + selectors: 'h1,h2,h3,h4', |
| 209 | + anchorName: function(i, heading, prefix) { |
| 210 | + heading = $(heading).text(); |
| 211 | + if (heading.trim) heading = heading.trim(); |
| 212 | + return heading.toLowerCase().replace(/ /g, '-').replace(/[^a-z^\-]+/g, ''); |
| 213 | + }, |
| 214 | + }) |
| 215 | +}) |
| 216 | +</script> |
| 217 | +</body> |
| 218 | +</html> |
0 commit comments