{"id":3185,"date":"2025-12-24T10:00:35","date_gmt":"2025-12-24T15:00:35","guid":{"rendered":"https:\/\/www.mymiller.name\/wordpress\/?p=3185"},"modified":"2025-12-24T10:00:35","modified_gmt":"2025-12-24T15:00:35","slug":"java-tips-part-3","status":"publish","type":"post","link":"https:\/\/www.mymiller.name\/wordpress\/java_tips\/java-tips-part-3\/","title":{"rendered":"Java Tips Part 3"},"content":{"rendered":"\n<p>Continuing my Java Tips from experience that I have learned from code reviews to different programming tasks.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"tip-11-use-hibernate-statistics\">Tip 11: Use Hibernate Statistics<\/h2>\n\n\n\n<p>Now, this is only for your development profiles\/environments, not for production.  Hibernate has built-in statistics on your queries.  This will break down how much time is spent along each step in the query.  A great tool for performance tuning.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nspring.jpa.properties.hibernate.generate_statistics=true\nlogging.level.org.hibernate.stat=DEBUG<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"tip-12-hibernate-slow-query-log\">Tip 12: Hibernate Slow Query Log<\/h2>\n\n\n\n<p>Following up using Hibernate Statistics, The difference here is this one is more suited for use on test, and production with a lower impact on performance.  In fact, this is highly recommended to use during performance testing.<\/p>\n\n\n\n<p>Using this feature you are able to specify what queries to log, if they take over x milliseconds then log the query for you to follow. In the example below we set it to 10ms.  You will need to determine the best value for your application. Also, remember not all queries are built the same.  A query to look up all users in the database won&#8217;t be as fast as a query to look up a single field from a single row in an indexed table.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>spring.jpa.properties.hibernate.session.events.log.LOG_QUERIES_SLOWER_THAN_MS=10<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"tip-13-use-resultsetextractor-on-queries\">Tip 13: Use ResultSetExtractor on Queries<\/h2>\n\n\n\n<p>Native queries in Hibernate\/JPA result in List&lt;Object[]> as our results.  This is not very clean to work with.  There is a very simple way to handle this, let&#8217;s say we have the following query: <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>String SQL = \"select first, last from Person\";\r\n      List &lt;Object&#91;]> results = jdbcTemplateObject.query(SQL);<\/code><\/pre>\n\n\n\n<p>This is going to give you all the records In the Person table, with 2 columns of data &#8220;first&#8221;, and &#8220;last&#8221;. Now you have to know that those 2 columns are Strings, that 0 is &#8220;first&#8221; and 1 is &#8220;last&#8221;. It would be far easier to push this code directly to a Person object.  So we create a ResultSetExtractor like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\tprivate static final class PersonEtractor implements ResultSetExtractor&lt;List&lt;Person>> {\r\n\r\n\t\t@Override\r\n\t\tpublic List&lt;Person> extractData(ResultSet resultSet) throws SQLException, DataAccessException {\r\n\r\n\t\t\tList&lt;Person> personList= new ArrayList&lt;>();\r\n\r\n\t\t\twhile (resultSet.next()) {\r\n\t\t\t\tPerson person= new Person();\r\n\t\t\t\tperson.setName(resultSet.getString(\"first\"));\r\n\t\t\t\tperson.setType(resultSet.getString(\"last\"));\r\n\t\t\t\tpersonList.add(equipment);\r\n\t\t\t}\r\n\t\t\treturn personList;\r\n\t\t}\r\n\t}\r\n<\/code><\/pre>\n\n\n\n<p>This is an extractor that is created as a separate class.  We could just as easily create this as an inline function.  However, then we couldn&#8217;t reuse the code if we needed to.  Now to use this in our query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>String SQL = \"select first, last from Person\";\n      List &lt;Object&#91;]> results = jdbcTemplateObject.query(SQL, new PersonExtractor());<\/code><\/pre>\n\n\n\n<p>Why do this v&#8217;s working with the List&lt;Object[]&gt;?<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Code Reuse<\/strong> &#8211; Queries can often get used in mulitple places in the code. Using this prevents duplicated code.<\/li><li><strong>Readability<\/strong> &#8211; Having the results in a POJO will make the code that use this easier to read.<\/li><li><strong>Mis-use<\/strong> &#8211; Having a POJO with defined types gives you a POJO with defined types that a user isn&#8217;t having to trying an identify the types.<\/li><li><strong>Identity <\/strong>&#8211; You do not have to know the query to know what the columns returned, as they are now defined in a POJO.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"tip-14-use-sqlresultsetmapping-instead-of-list-object\">Tip 14: Use @SqlResultSetMapping instead of List&lt;Object[]><\/h2>\n\n\n\n<p>While not going into a full-length article here on how to use @SqlResultSetMapping, I am going to explain why you want to do this. In many cases, you do not want to work with a List&lt;Object[]&gt; results from a query.  You&#8217;re going to want to have that into a POJO, of some sort.  There are 2 ways to do this, @SqlResultSetMapping, and a ResultSetExtractor (Tip 13).  This method uses annotations to set up the transformation of your data.  For a more detailed description of exactly how to use this, look here <a href=\"https:\/\/www.baeldung.com\/jpa-sql-resultset-mapping\" data-type=\"URL\" data-id=\"https:\/\/www.baeldung.com\/jpa-sql-resultset-mapping\">Baeldung &#8211; A Guide to SqlResultSetMapping<\/a>.<\/p>\n\n\n\n<p>Why do this v&#8217;s working with the List&lt;Object[]&gt;?<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Code Reuse<\/strong> &#8211; Queries can often get used in mulitple places in the code. Using this prevents duplicated code.<\/li><li><strong>Readability<\/strong> &#8211; Having the results in a POJO will make the code that use this easier to read.<\/li><li><strong>Mis-use<\/strong> &#8211; Having a POJO with defined types gives you a POJO with defined types that a user isn&#8217;t having to trying an identify the types.<\/li><li><strong>Identity <\/strong>&#8211; You do not have to know the query to know what the columns returned, as they are now defined in a POJO.<\/li><\/ul>\n\n\n\n<p><em>Now you ask why do this over the ResultSetExtractor (Tip 13)?<\/em><\/p>\n\n\n\n<p>They both can accomplish the same thing, so then it becomes a preference of your coding style.  However, ResultSetExtractor has an advantage over this.  You may have cases where you have the same query, but you want it handled differently.  Now in this case you simply use a different ResultSetExtractor. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"tip-15-pad-hibernate-parameters-in-in-clause\">Tip 15: Pad Hibernate Parameters in &#8220;IN&#8221; clause<\/h2>\n\n\n\n<p>This one is a little confusing, it took me a while to fully understand this change.  Let&#8217;s say we have two queries:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>List&lt;Person&gt; people = personRepository.findAllById(Arrays.asList(10L, 12L, 17L 33L));\n<\/code><\/pre>\n\n\n\n<p>This will of course find the Person records with IDs 10, 12, 17 &amp; 33.  Hibernate will create a cached plan that it will use to perform the query.  Now if our second query is like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>List&lt;Person&gt; people = personRepository.findAllById(Arrays.asList(4L, 71L 101L));<\/code><\/pre>\n\n\n\n<p>Hibernate will create an entirely new plan and cache it.  Because it does now have the same number of parameters for the &#8220;IN&#8221; clause.  This slows down the query as it has to generate a new plan.  Hibernate has a way to improve it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>spring.jpa.properties.hibernate.query.in_clause_parameter_padding=true<\/code><\/pre>\n\n\n\n<p>This tells Hibernate to use padding, which allows it to pad up to the next 2^n parameters.  This means these two queries would now use the same plan, not requiring a new plan to be generated and a higher number of hits in your cache.  That increases your performance and makes your queries more efficient.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Continuing my Java Tips from experience that I have learned from code reviews to different programming tasks. Tip 11: Use Hibernate Statistics Now, this is only for your development profiles\/environments, not for production. Hibernate has built-in statistics on your queries. This will break down how much time is spent along each step in the query. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3129,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","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":"","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}},"categories":[452],"tags":[69,361,362],"series":[360],"class_list":["post-3185","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java_tips","tag-java-2","tag-java-tips","tag-tips","series-java-tips"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"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","jetpack-related-posts":[{"id":3249,"url":"https:\/\/www.mymiller.name\/wordpress\/java_tips\/java-tips-part-5\/","url_meta":{"origin":3185,"position":0},"title":"Java Tips Part 5","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Tip 21: Use Prepared Statements When working with JPA\/Hibernate make use of Prepared Statements that can be reused. Basically, I'm saying do not do the following: Query query = JPA.em().createNativeQuery(\"select count(*) from user u inner join\" + \"address a where a.user_id=u.id and a.city='\" + city + \"'\"); BigInteger val =\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":3153,"url":"https:\/\/www.mymiller.name\/wordpress\/architecture\/performance-nanoseconds-now-not-milliseconds\/","url_meta":{"origin":3185,"position":1},"title":"Performance?  nanoseconds, not milliseconds!","author":"Jeffery Miller","date":"March 12, 2022","format":false,"excerpt":"In today's time of high-performance computing, we no longer have the luxury of measuring our time in milliseconds, we need to move past this into nanoseconds. When I first started programming in the '90s we measured our code in seconds. That quickly gave way to milliseconds, even before the '90s\u2026","rel":"","context":"In &quot;Architecture&quot;","block_context":{"text":"Architecture","link":"https:\/\/www.mymiller.name\/wordpress\/category\/architecture\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2022\/01\/superhero-g470982bed_640.jpg?fit=640%2C418&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2022\/01\/superhero-g470982bed_640.jpg?fit=640%2C418&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2022\/01\/superhero-g470982bed_640.jpg?fit=640%2C418&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":3185,"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":2391,"url":"https:\/\/www.mymiller.name\/wordpress\/java_tips\/java-development-tips\/","url_meta":{"origin":3185,"position":3},"title":"Java Development Tips","author":"Jeffery Miller","date":"December 23, 2025","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":3213,"url":"https:\/\/www.mymiller.name\/wordpress\/java_tips\/java-tips-part-4\/","url_meta":{"origin":3185,"position":4},"title":"Java Tips Part 4","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 16: Perform Bulk operations with Native Queries, or Stored Procedure It can be very tempting to do an update like the following: List<Person> people = ListUtils.safe(personRepository.findAll()).stream().filter person -> person.getAge() >= 60 ).map(person\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":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":3185,"position":5},"title":"Spring Data JPA &#038; Java Records: The Ultimate Duo for Clean, Fast Query Projections","author":"Jeffery Miller","date":"November 20, 2025","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":[]}],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3185","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=3185"}],"version-history":[{"count":4,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3185\/revisions"}],"predecessor-version":[{"id":3219,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3185\/revisions\/3219"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media\/3129"}],"wp:attachment":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media?parent=3185"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/categories?post=3185"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/tags?post=3185"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/series?post=3185"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}