{"id":3374,"date":"2025-12-24T10:01:05","date_gmt":"2025-12-24T15:01:05","guid":{"rendered":"https:\/\/www.mymiller.name\/wordpress\/?p=3374"},"modified":"2025-12-24T10:01:05","modified_gmt":"2025-12-24T15:01:05","slug":"spring-data-with-java-records","status":"publish","type":"post","link":"https:\/\/www.mymiller.name\/wordpress\/spring_databases\/spring-data-with-java-records\/","title":{"rendered":"Spring Data with Java Records"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Java records are a new feature introduced in Java 14 that provides a concise way to declare classes that are meant to hold immutable data. Spring Data is a popular framework for building data access layers in Java applications. In this answer, we will explain how to use Java records as models in Spring Data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To use a Java record as a model in Spring Data, you can follow these steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Define the record class: Define a record class with the fields you need for your model. For example:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>public record Customer(String firstName, String lastName, String email) {}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This record class defines a customer model with three fields: <code>firstName<\/code>, <code>lastName<\/code>, and <code>email<\/code>. Since records are immutable by default, the <code>Customer<\/code> class is automatically final and its fields are final as well.<\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"2\">\n<li>Define the Spring Data repository: Define a Spring Data repository interface that extends <code>JpaRepository<\/code> or one of its sub-interfaces. For example:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>@Repository \npublic interface CustomerRepository extends JpaRepository&lt;Customer, Long&gt; {}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This repository interface defines a Spring Data repository for the <code>Customer<\/code> model. The <code>JpaRepository<\/code> interface provides basic CRUD operations for the model, and you can define additional custom methods if needed.<\/p>\n\n\n\n<ol class=\"wp-block-list\" start=\"3\">\n<li>Use the model in your application: You can now use the <code>Customer<\/code> model in your Spring application, for example in a service or controller class. For example:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>@Service \npublic class CustomerService {\n\tprivate final CustomerRepository customerRepository;      \n\tpublic CustomerService(CustomerRepository customerRepository) {\n\t   this.customerRepository = customerRepository;     \n\t}\n\t\n\tpublic List&lt;Customer&gt; findAllCustomers() {\n\t\treturn customerRepository.findAll();\n\t}\n\t\n\tpublic Customer createCustomer(Customer customer) {         \n\t\treturn customerRepository.save(customer);\n\t}\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This service class uses the <code>CustomerRepository<\/code> to find and create customers. Since the <code>Customer<\/code> model is defined as a record, you can easily create instances of it using its constructor syntax, for example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Customer customer = new Customer(\"John\", \"Doe\", \"john.doe@example.com\"); customerService.createCustomer(customer);\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Updating records in Spring Data when your models are Java records can be done using the <code>save<\/code> method provided by the Spring Data repository interface.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When you use a Java record as a model, its fields are immutable by default, so you can&#8217;t change them directly. Instead, you can create a new instance of the record with the updated values and use the <code>save<\/code> method to persist the changes to the database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s an example of how to update a record in Spring Data when your models are Java records:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Define the record class: Define a record class with the fields you need for your model, as explained in the previous answer.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">javaCopy code<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public record Customer(String firstName, String lastName, String email) {}\n<\/code><\/pre>\n\n\n\n<ol class=\"wp-block-list\" start=\"2\">\n<li>Define the Spring Data repository: Define a Spring Data repository interface that extends <code>JpaRepository<\/code> or one of its sub-interfaces, as explained in the previous answer.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">javaCopy code<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@Repository \npublic interface CustomerRepository extends JpaRepository&lt;Customer, Long&gt; {}\n<\/code><\/pre>\n\n\n\n<ol class=\"wp-block-list\" start=\"3\">\n<li>Update a record: To update a record, you can retrieve it from the repository, create a new instance with the updated values, and save the new instance using the <code>save<\/code> method.<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>@Service \npublic class CustomerService {\n\tprivate final CustomerRepository customerRepository;      \n\t\n\tpublic CustomerService(CustomerRepository customerRepository) {         \n\t\tthis.customerRepository = customerRepository;     \n\t}\n\t\n\tpublic Customer updateCustomer(Long id, Customer updatedCustomer) {         \n\t\tCustomer customer = customerRepository.findById(id)\n\t\t\t.orElseThrow(() -&gt; \n\t\t\t\tnew EntityNotFoundException(\"Customer not found with id: \" + id));\n\t\tCustomer newCustomer = new Customer(updatedCustomer.firstName(), \n\t\t\tupdatedCustomer.lastName(), updatedCustomer.email());         \n\t\t\t\n\t\t\tnewCustomer = customerRepository.save(newCustomer);\n\t\treturn newCustomer;\n\t}\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In this example, the <code>updateCustomer<\/code> method retrieves a customer from the repository using its ID, creates a new instance of the <code>Customer<\/code> record with the updated values, and saves it to the database using the <code>save<\/code> method.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Note that in this example, we are creating a new instance of the record instead of updating the existing instance. This is because records are immutable by default, so we can&#8217;t change the values of an existing instance. Instead, we create a new instance with the updated values and save it to the database.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Java records are a new feature introduced in Java 14 that provides a concise way to declare classes that are meant to hold immutable data. Spring Data is a popular framework for building data access layers in Java applications. In this answer, we will explain how to use Java records as models in Spring Data. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3376,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[435],"tags":[],"series":[397],"class_list":["post-3374","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-spring_databases","series-spring"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2023\/06\/office-work-gc63fa3774_640.jpg?fit=640%2C430&ssl=1","jetpack-related-posts":[{"id":3925,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_databases\/spring-data-jpa-java-records-the-ultimate-duo-for-clean-fast-query-projections\/","url_meta":{"origin":3374,"position":0},"title":"Spring Data JPA &#038; Java Records: The Ultimate Duo for Clean, Fast Query Projections","author":"Jeffery Miller","date":"April 20, 2026","format":false,"excerpt":"Architecting Efficient Data Access with Immutability As Spring developers, we spend a significant amount of time optimizing the path between the database and the client. One of the most common performance pitfalls is the over-fetching of data\u2014loading entire, complex JPA entities when all we need is a small subset of\u2026","rel":"","context":"In &quot;Spring Databases&quot;","block_context":{"text":"Spring Databases","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_databases\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/record-shop-9180482_1280.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/record-shop-9180482_1280.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/record-shop-9180482_1280.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/record-shop-9180482_1280.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/record-shop-9180482_1280.avif 3x"},"classes":[]},{"id":2391,"url":"https:\/\/www.mymiller.name\/wordpress\/java_tips\/java-development-tips\/","url_meta":{"origin":3374,"position":1},"title":"Java Development Tips","author":"Jeffery Miller","date":"April 20, 2026","format":false,"excerpt":"Java-based servers or applications often have to deal with large amounts of data.\u00a0 Whether the data is from a database, or from a local file, processing this data in an efficient manner is a priority for maintainability. In this article, we will discuss the types of Java Data Objects and\u2026","rel":"","context":"In &quot;Java Tips&quot;","block_context":{"text":"Java Tips","link":"https:\/\/www.mymiller.name\/wordpress\/category\/java_tips\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2018\/10\/archive-1850170_640.jpg?fit=640%2C426&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2018\/10\/archive-1850170_640.jpg?fit=640%2C426&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2018\/10\/archive-1850170_640.jpg?fit=640%2C426&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":3148,"url":"https:\/\/www.mymiller.name\/wordpress\/java_tips\/java-tips-part-2\/","url_meta":{"origin":3374,"position":2},"title":"Java Tips Part 2","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Continuing my Java Tips from experience that I have learned from code reviews to different programming tasks. Tip 6: Don't call .toString() on slf4j logging calls. So if you're following my other tips and using the formatting option of the logging messages like this: list.parallelStream().filter(item -> !item.contains(\"BOB\")).forEach(item -> logger.debug(\"Item: {}\u2026","rel":"","context":"In &quot;Java Tips&quot;","block_context":{"text":"Java Tips","link":"https:\/\/www.mymiller.name\/wordpress\/category\/java_tips\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2021\/12\/sam-dan-truong-rF4kuvgHhU-unsplash-scaled-e1640791434235.jpg?fit=640%2C427&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2021\/12\/sam-dan-truong-rF4kuvgHhU-unsplash-scaled-e1640791434235.jpg?fit=640%2C427&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2021\/12\/sam-dan-truong-rF4kuvgHhU-unsplash-scaled-e1640791434235.jpg?fit=640%2C427&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":3530,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_databases\/spring-jpa-auditing-track-data-changes\/","url_meta":{"origin":3374,"position":3},"title":"Spring JPA Auditing: Track Data Changes","author":"Jeffery Miller","date":"April 20, 2026","format":false,"excerpt":"In the dynamic world of software development, understanding the complete history of your data is crucial. Who made a change? When did it occur? Who viewed the data? Spring JPA Auditing, combined with custom solutions, offers a comprehensive way to answer these questions, acting as a time machine for your\u2026","rel":"","context":"In &quot;Spring Databases&quot;","block_context":{"text":"Spring Databases","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_databases\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/image.png?fit=1200%2C686&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/image.png?fit=1200%2C686&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/image.png?fit=1200%2C686&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/image.png?fit=1200%2C686&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/image.png?fit=1200%2C686&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":3881,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_messaging\/mastering-polymorphic-data-in-spring-kafka-with-avro-with-dedicated-topics\/","url_meta":{"origin":3374,"position":4},"title":"Mastering Polymorphic Data in Spring Kafka with Avro with Dedicated Topics","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"As a software architect, designing robust, scalable, and adaptable distributed systems is a constant pursuit. When working with Apache Kafka, a common challenge arises: how do you send messages that, while adhering to a generic wrapper, can carry different types of payloads based on the specific event or context? In\u2026","rel":"","context":"In &quot;Spring Messaging&quot;","block_context":{"text":"Spring Messaging","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_messaging\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/06\/migration-8576653_1280.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/06\/migration-8576653_1280.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/06\/migration-8576653_1280.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/06\/migration-8576653_1280.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/06\/migration-8576653_1280.avif 3x"},"classes":[]},{"id":3884,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_messaging\/mastering-polymorphic-data-in-spring-kafka-with-avro-union-types\/","url_meta":{"origin":3374,"position":5},"title":"Mastering Polymorphic Data in Spring Kafka with Avro Union Types","author":"Jeffery Miller","date":"April 20, 2026","format":false,"excerpt":"As a software architect, designing robust, scalable, and adaptable distributed systems is a constant pursuit. When working with Apache Kafka, a common challenge arises: how do you send messages that, while adhering to a generic wrapper, can carry different types of payloads based on the specific event or context? Imagine\u2026","rel":"","context":"In &quot;Spring Messaging&quot;","block_context":{"text":"Spring Messaging","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_messaging\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/06\/plastic-5527530_1280.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/06\/plastic-5527530_1280.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/06\/plastic-5527530_1280.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/06\/plastic-5527530_1280.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/06\/plastic-5527530_1280.avif 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3374","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/comments?post=3374"}],"version-history":[{"count":3,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3374\/revisions"}],"predecessor-version":[{"id":3379,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3374\/revisions\/3379"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media\/3376"}],"wp:attachment":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media?parent=3374"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/categories?post=3374"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/tags?post=3374"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/series?post=3374"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}