{"id":1010,"date":"2017-12-22T00:01:07","date_gmt":"2017-12-22T00:01:07","guid":{"rendered":"https:\/\/www.javaadvent.com\/?p=1010"},"modified":"2019-11-27T09:47:38","modified_gmt":"2019-11-27T09:47:38","slug":"power-data-model-projections","status":"publish","type":"post","link":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html","title":{"rendered":"Power Up Your Data Model With Projections"},"content":{"rendered":"<h2 id=\"_introduction\">Introduction<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Data models can be tricky. Modelling can be even harder. Sometimes information that should go into a database table isn\u2019t necessarily what we want to go out to every piece of code.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>And like so many other times, Spring comes to the rescue. A little feature called <em>projection<\/em> helps us to map data with only a few lines in an ordinary interface.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>In this article, we are going to see a simple example of how we can use projections.<\/p>\n<h2 id=\"_the_basics\">The Basics<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>OK, let\u2019s set the scene. Imagine we have the following entity:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@Builder\r\n@Data\r\n@NoArgsConstructor\r\n@AllArgsConstructor\r\n@Entity\r\n@Table\r\n@EqualsAndHashCode(doNotUseGetters = true)\r\n@ToString(doNotUseGetters = true)\r\npublic class User implements Serializable {\r\n \r\n @Id\r\n @SequenceGenerator(name = &quot;user_seq&quot;, sequenceName = &quot;user_seq&quot;)\r\n @GeneratedValue(strategy = GenerationType.IDENTITY, generator = &quot;user_seq&quot;)\r\n private Long id;\r\n \r\n @Basic\r\n private String username;\r\n \r\n @Basic\r\n private String salt;\r\n \r\n @Basic\r\n private String password;\r\n \r\n @Basic\r\n private String firstName;\r\n \r\n @Basic\r\n private String lastName;\r\n}\r\n<\/pre>\n<div class=\"paragraph\">\n<p>Some explanation might be helpful here: Let\u2019s have a look at the annotations. I am lazy, honestly, so <a href=\"https:\/\/projectlombok.org\">Lombok<\/a> is right up my alley. Lombok gives us a nice declarative way to say we need:<\/p>\n<ul>\n<li>a nice builder interface to create the bean (<code>@Builder<\/code>)<\/li>\n<li>Getters and setter (<code>@Data<\/code>)<\/li>\n<li>a default constructor (<code>@NoArgsConstructor<\/code>)<\/li>\n<li>one more constructor with arguments for all fields (<code>@AllArgsConstructor<\/code>)<\/li>\n<li><code>equals()<\/code> and <code>hashCode()<\/code>, but please use the fields, not the getters (<code>@EqualsAndHashCode(doNotUseGetters = true)<\/code>)<\/li>\n<li><code>toString()<\/code>; again, use the fields (<code>@ToString(doNotUseGetter = true)<\/code>)<\/li>\n<\/ul>\n<\/div>\n<div class=\"paragraph\">\n<p>The remaining annotations (<code>@Entity<\/code> and <code>@Table<\/code>) are good old JPA.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Right, so, we have a nice entity. What\u2019s the issue?<\/p>\n<h2 id=\"_get_data_the_traditional_way\">Get Data The Traditional way<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Let\u2019s have a look at this repository:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@Repository\r\npublic interface UserRepository extends JpaRepository&amp;lt;User, Long&amp;gt; {\r\n\r\n}\r\n\r\n<\/pre>\n<div class=\"sect1\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The above code provides us with a minimal set of CRUD methods. One is <code>getOne(Long id)<\/code>. Good, isn\u2019t it?<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Well, the correct answer must be: It depends! Why? Because this returns the whole entity, including the salt and the hashed password. This is very sensitive information. Especially the salt should never be available to the outside world.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>In order to get this information out of the resulting entity, we would have to do a lot of manual work. Just from the top of my head, we should: * create a new bean * implement a mapper to get from our entity to the new bean * make sure every time we deal with that entity, we also map it * getting headaches when realising there are also multiple results possible.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_return_of_the_minimum_necessary\">Return The Minimum Necessary<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Thankfully, Spring safes the day. A little feature called <em>Projections<\/em> lets us define the mapping in a declarative way. Such an interface could look like that:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic interface UserProjection {\r\n \r\n @Value(&quot;#{target.getUsername()}&quot;)\r\n String getUsername();\r\n \r\n @Value(&quot;#{target.getFirstName()}&quot;)\r\n String getFirstName();\r\n \r\n @Value(&quot;#{target.getLastName()}&quot;)\r\n String getLastName();\r\n}\r\n<\/pre>\n<div class=\"paragraph\">\n<p>Spring will replace <code>target<\/code> with the entity we are currently dealing with. In other words, <code>target<\/code> will be an instance of <code>User<\/code>.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>The only thing we have to do now is something like this:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@Repository\r\npublic interface UserRepository extends JpaRepository&amp;lt;User, Long&amp;gt; {\r\n \r\n UserProjection findById(Long id);\r\n \r\n List&amp;lt;UserProjection&amp;gt; findAllUser();\r\n}\r\n<\/pre>\n<div class=\"sect1\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Now, every time we call <code>findById()<\/code>, we will get an instance of <code>UserProjection<\/code>. No leakage of our salt or password hash possible! Even better, we can use the same procedure for methods with multiple results.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_conclusion\">Conclusion<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>We can save a lot of code and pain with Spring Projections. And the <code>@Value()<\/code> definitions can get as complex as we need it. In my current project, for example, this saves my team a lot of boilerplate code when we map an &#8220;interesting&#8221; legacy database design into easier data models.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>If you want to give this a spin, you can find a simple example application on <a href=\"https:\/\/github.com:steinhauer-software\/javaadvent2018-spring-projection\">GitHub<\/a>.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Data models can be tricky. Modelling can be even harder. Sometimes information that should go into a database table isn\u2019t necessarily what we want to go out to every piece of code. And like so many other times, Spring comes to the rescue. A little feature called projection helps us to map data with [&hellip;]<\/p>\n","protected":false},"author":23,"featured_media":1102,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[276,11],"tags":[],"coauthors":[],"class_list":["post-1010","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-276","category-java"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Power Up Your Data Model With Projections - JVM Advent<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Power Up Your Data Model With Projections - JVM Advent\" \/>\n<meta property=\"og:description\" content=\"Introduction Data models can be tricky. Modelling can be even harder. Sometimes information that should go into a database table isn\u2019t necessarily what we want to go out to every piece of code. And like so many other times, Spring comes to the rescue. A little feature called projection helps us to map data with [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html\" \/>\n<meta property=\"og:site_name\" content=\"JVM Advent\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Java-Advent-Calendar-229536173843473\/\" \/>\n<meta property=\"article:published_time\" content=\"2017-12-22T00:01:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-11-27T09:47:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javaadvent.com\/content\/uploads\/2017\/12\/duke22.png\" \/>\n\t<meta property=\"og:image:width\" content=\"280\" \/>\n\t<meta property=\"og:image:height\" content=\"280\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Holger Steinhauer\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/SteinhSoftware\" \/>\n<meta name=\"twitter:site\" content=\"@javaadvent\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Holger Steinhauer\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html\"},\"author\":{\"name\":\"Holger Steinhauer\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#\\\/schema\\\/person\\\/4a21f9f29de7b5c473df81084354eb34\"},\"headline\":\"Power Up Your Data Model With Projections\",\"datePublished\":\"2017-12-22T00:01:07+00:00\",\"dateModified\":\"2019-11-27T09:47:38+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html\"},\"wordCount\":626,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2017\\\/12\\\/duke22.png?fit=280%2C280&ssl=1\",\"articleSection\":[\"2017\",\"java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html\",\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html\",\"name\":\"Power Up Your Data Model With Projections - JVM Advent\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2017\\\/12\\\/duke22.png?fit=280%2C280&ssl=1\",\"datePublished\":\"2017-12-22T00:01:07+00:00\",\"dateModified\":\"2019-11-27T09:47:38+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#\\\/schema\\\/person\\\/4a21f9f29de7b5c473df81084354eb34\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2017\\\/12\\\/duke22.png?fit=280%2C280&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/www.javaadvent.com\\\/content\\\/uploads\\\/2017\\\/12\\\/duke22.png?fit=280%2C280&ssl=1\",\"width\":280,\"height\":280},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/2017\\\/12\\\/power-data-model-projections.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javaadvent.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Power Up Your Data Model With Projections\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/\",\"name\":\"JVM Advent\",\"description\":\"The JVM Programming Advent Calendar\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javaadvent.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javaadvent.com\\\/#\\\/schema\\\/person\\\/4a21f9f29de7b5c473df81084354eb34\",\"name\":\"Holger Steinhauer\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3bf104a9686c82683b5666b5b35f70d56304ae504ba7d16a21c34ba32543a7d4?s=96&d=retro&r=g0d16ae42e2a9ddccabfd017cb6a93641\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3bf104a9686c82683b5666b5b35f70d56304ae504ba7d16a21c34ba32543a7d4?s=96&d=retro&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/3bf104a9686c82683b5666b5b35f70d56304ae504ba7d16a21c34ba32543a7d4?s=96&d=retro&r=g\",\"caption\":\"Holger Steinhauer\"},\"description\":\"I am a passionate software developer with a DevOps mindset. I love all things Kotlin and have more than 15 years of experience in the market. Besides coding, I run the Virtual Kotlin User Group, co-organise the Kotlin User Group Berlin, started my own podcast Coding with Holger and founded the digital IT consultancy for the 21st century.\",\"sameAs\":[\"http:\\\/\\\/steinhauer.software\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/holgersteinhauer\\\/\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/SteinhSoftware\"],\"url\":\"https:\\\/\\\/www.javaadvent.com\\\/author\\\/daincredibleholg\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Power Up Your Data Model With Projections - JVM Advent","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html","og_locale":"en_US","og_type":"article","og_title":"Power Up Your Data Model With Projections - JVM Advent","og_description":"Introduction Data models can be tricky. Modelling can be even harder. Sometimes information that should go into a database table isn\u2019t necessarily what we want to go out to every piece of code. And like so many other times, Spring comes to the rescue. A little feature called projection helps us to map data with [&hellip;]","og_url":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html","og_site_name":"JVM Advent","article_publisher":"https:\/\/www.facebook.com\/Java-Advent-Calendar-229536173843473\/","article_published_time":"2017-12-22T00:01:07+00:00","article_modified_time":"2019-11-27T09:47:38+00:00","og_image":[{"width":280,"height":280,"url":"https:\/\/www.javaadvent.com\/content\/uploads\/2017\/12\/duke22.png","type":"image\/png"}],"author":"Holger Steinhauer","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/SteinhSoftware","twitter_site":"@javaadvent","twitter_misc":{"Written by":"Holger Steinhauer","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html#article","isPartOf":{"@id":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html"},"author":{"name":"Holger Steinhauer","@id":"https:\/\/www.javaadvent.com\/#\/schema\/person\/4a21f9f29de7b5c473df81084354eb34"},"headline":"Power Up Your Data Model With Projections","datePublished":"2017-12-22T00:01:07+00:00","dateModified":"2019-11-27T09:47:38+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html"},"wordCount":626,"commentCount":0,"image":{"@id":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2017\/12\/duke22.png?fit=280%2C280&ssl=1","articleSection":["2017","java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html","url":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html","name":"Power Up Your Data Model With Projections - JVM Advent","isPartOf":{"@id":"https:\/\/www.javaadvent.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html#primaryimage"},"image":{"@id":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2017\/12\/duke22.png?fit=280%2C280&ssl=1","datePublished":"2017-12-22T00:01:07+00:00","dateModified":"2019-11-27T09:47:38+00:00","author":{"@id":"https:\/\/www.javaadvent.com\/#\/schema\/person\/4a21f9f29de7b5c473df81084354eb34"},"breadcrumb":{"@id":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html#primaryimage","url":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2017\/12\/duke22.png?fit=280%2C280&ssl=1","contentUrl":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2017\/12\/duke22.png?fit=280%2C280&ssl=1","width":280,"height":280},{"@type":"BreadcrumbList","@id":"https:\/\/www.javaadvent.com\/2017\/12\/power-data-model-projections.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javaadvent.com\/"},{"@type":"ListItem","position":2,"name":"Power Up Your Data Model With Projections"}]},{"@type":"WebSite","@id":"https:\/\/www.javaadvent.com\/#website","url":"https:\/\/www.javaadvent.com\/","name":"JVM Advent","description":"The JVM Programming Advent Calendar","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javaadvent.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.javaadvent.com\/#\/schema\/person\/4a21f9f29de7b5c473df81084354eb34","name":"Holger Steinhauer","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/3bf104a9686c82683b5666b5b35f70d56304ae504ba7d16a21c34ba32543a7d4?s=96&d=retro&r=g0d16ae42e2a9ddccabfd017cb6a93641","url":"https:\/\/secure.gravatar.com\/avatar\/3bf104a9686c82683b5666b5b35f70d56304ae504ba7d16a21c34ba32543a7d4?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3bf104a9686c82683b5666b5b35f70d56304ae504ba7d16a21c34ba32543a7d4?s=96&d=retro&r=g","caption":"Holger Steinhauer"},"description":"I am a passionate software developer with a DevOps mindset. I love all things Kotlin and have more than 15 years of experience in the market. Besides coding, I run the Virtual Kotlin User Group, co-organise the Kotlin User Group Berlin, started my own podcast Coding with Holger and founded the digital IT consultancy for the 21st century.","sameAs":["http:\/\/steinhauer.software","https:\/\/www.linkedin.com\/in\/holgersteinhauer\/","https:\/\/x.com\/https:\/\/twitter.com\/SteinhSoftware"],"url":"https:\/\/www.javaadvent.com\/author\/daincredibleholg"}]}},"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2017\/12\/duke22.png?fit=280%2C280&ssl=1","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":2054,"url":"https:\/\/www.javaadvent.com\/2019\/12\/the-best-way-to-prevent-java-persistence-and-hibernate-issues.html","url_meta":{"origin":1010,"position":0},"title":"The best way to prevent Java Persistence and Hibernate performance issues","author":"Vlad Mihalcea","date":"December 12, 2019","format":false,"excerpt":"Introduction Many years ago, I used to work as a team leader, and, one day, the General Manager asked me to take a look at a project that was in big trouble. The application in question had been developed by a team of software developers for over 9 months, and\u2026","rel":"","context":"In &quot;2019&quot;","block_context":{"text":"2019","link":"https:\/\/www.javaadvent.com\/category\/christmas-2019-is-coming"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2018\/12\/duke12.png?fit=280%2C280&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":6132,"url":"https:\/\/www.javaadvent.com\/2025\/12\/spec-driven-development-in-practice-how-ai-simplify-full-stack-java.html","url_meta":{"origin":1010,"position":1},"title":"Spec-Driven Development in Practice: How AI Simplify Full-Stack Java","author":"Simon Martinelli","date":"December 14, 2025","format":false,"excerpt":"AI is changing how we build software, but many teams still work as if nothing has changed. They treat code as the only reliable artifact. Everything else slowly gets outdated: Requirements documents drift away from reality Diagrams do not match the current architecture Tests only cover part of the behavior\u2026","rel":"","context":"In &quot;2025&quot;","block_context":{"text":"2025","link":"https:\/\/www.javaadvent.com\/category\/2025"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-14.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-14.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-14.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-14.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":5966,"url":"https:\/\/www.javaadvent.com\/2025\/12\/how-understanding-request-flow-in-spring-boot-changed-the-way-i-code.html","url_meta":{"origin":1010,"position":2},"title":"How Understanding Request Flow in Spring Boot Changed the Way I Code","author":"Mohammed","date":"December 3, 2025","format":false,"excerpt":"When I first stepped into backend development, I believed programming was only about one thing: \u201cIf the output comes, the job is done.\u201d I bundled everything into one giant file \u2014 controllers, logic, database access.I didn\u2019t understand why Spring insisted on layers or why DI, IoC, and annotations were so\u2026","rel":"","context":"In &quot;2025&quot;","block_context":{"text":"2025","link":"https:\/\/www.javaadvent.com\/category\/2025"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-3.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-3.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-3.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-3.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":5147,"url":"https:\/\/www.javaadvent.com\/2024\/12\/cqrs-meets-modern-java.html","url_meta":{"origin":1010,"position":3},"title":"CQRS meets modern Java","author":"Simon Martinelli","date":"December 8, 2024","format":false,"excerpt":"The development of powerful yet maintainable software solutions remains at the heart of modern software development. The Command Query Responsibility Segregation (CQRS) pattern offers an efficient method for this by creating a clear separation between executing commands and querying data, which simplifies the system architecture and improves performance. At the\u2026","rel":"","context":"In &quot;2024&quot;","block_context":{"text":"2024","link":"https:\/\/www.javaadvent.com\/category\/2024"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-8.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-8.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-8.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-8.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":4482,"url":"https:\/\/www.javaadvent.com\/2023\/12\/making-data-transformation-easy-with-mapstruct.html","url_meta":{"origin":1010,"position":4},"title":"Making data transformation easy with MapStruct","author":"Vladimir Dejanovic","date":"December 7, 2023","format":false,"excerpt":"Motivation Most applications in the world follow a simple format. They ingest some data, do some transformation on it, and then expose this transformed data to their consumers. If we look at a high enough level, we will see this pattern in all applications. The transformation part can be very\u2026","rel":"","context":"In &quot;2023&quot;","block_context":{"text":"2023","link":"https:\/\/www.javaadvent.com\/category\/2023"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-7.png?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-7.png?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-7.png?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2021\/12\/Feature-Image-Day-7.png?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1300,"url":"https:\/\/www.javaadvent.com\/2018\/12\/how-to-map-postgresql-enums-to-jpa-entity-properties-using-hibernate.html","url_meta":{"origin":1010,"position":5},"title":"How to map PostgreSQL Enums to JPA entity properties using Hibernate","author":"Vlad Mihalcea","date":"December 6, 2018","format":false,"excerpt":"Introduction The open-source hibernate-types project allows you to map JSON, ARRAY, YearMonth, Month or database-specific columns (e.g. INET addresses). In this article, we are going to see how you can map a PostgreSQL Enum type to a Java array when using JPA and Hibernate. Maven dependency First of all, you\u2026","rel":"","context":"In &quot;2018&quot;","block_context":{"text":"2018","link":"https:\/\/www.javaadvent.com\/category\/2018"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.javaadvent.com\/content\/uploads\/2018\/12\/duke6.png?fit=280%2C280&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]}],"jetpack_likes_enabled":true,"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts\/1010","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/users\/23"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/comments?post=1010"}],"version-history":[{"count":13,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts\/1010\/revisions"}],"predecessor-version":[{"id":1058,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/posts\/1010\/revisions\/1058"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/media\/1102"}],"wp:attachment":[{"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/media?parent=1010"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/categories?post=1010"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/tags?post=1010"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.javaadvent.com\/wp-json\/wp\/v2\/coauthors?post=1010"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}