{"id":1997,"date":"2016-04-20T00:00:00","date_gmt":"2016-04-19T22:00:00","guid":{"rendered":"\/\/thorben-janssen.com\/?p=1997"},"modified":"2021-10-31T16:15:51","modified_gmt":"2021-10-31T15:15:51","slug":"database-functions","status":"publish","type":"post","link":"https:\/\/thorben-janssen.com\/database-functions\/","title":{"rendered":"How to call custom database functions with JPA and Hibernate"},"content":{"rendered":"\n<p><span style=\"font-size: inherit;\">JPA supports a set of database functions which you can use to perform small operations and transformations within a query. This is often easier and faster than doing it in the Java code.<\/span><\/p>\n\n\n\n<p>But how do you call functions which are not supported by the JPA standard, like database-specific ones or the custom functions implemented by your database team?<\/p>\n\n\n\n<p><a href=\"\/\/thorben-janssen.com\/jpa-native-queries\/\">Native queries<\/a>&nbsp;are of course one option.&nbsp;Another one is the function function<em>()<\/em> which was <a href=\"\/\/thorben-janssen.com\/jpa-21-overview\/\">introduced in JPA 2.1<\/a> and allows you to call any function in a JPQL or Criteria query.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Database function<\/h2>\n\n\n\n<p>Let&#8217;s have a look at the custom database function, before I show you the Java code. As you can see in the following code snippet, the function is pretty simple. It takes two input parameters of type double and calculates their sum.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted brush: java; gutter: true\">\nCREATE OR REPLACE FUNCTION calculate(\n    IN x double precision,\n    IN y double precision,\n    OUT sum double precision)\n  RETURNS double precision AS\nBEGIN\n    sum = x + y;\nEND;\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Call a custom database function<\/h2>\n\n\n\n<p>JPA 2.1 introduced <em>function()<\/em>&nbsp;to call database functions which are not directly supported by the standard. As you can see in the following code snippet, the syntax is pretty easy. You provide the name of the function as the first parameter&nbsp;and then all parameters&nbsp;of the custom function. In this example, the name of the function is &#8220;calculate&#8221; and I provide the numbers 1 and 2 as parameters.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted brush: java; gutter: true\">\nAuthor a = em.createQuery(&quot;SELECT a FROM Author a WHERE a.id = function(&#039;calculate&#039;, 1, 2)&quot;, Author.class).getSingleResult();\n<\/pre>\n\n\n\n<div class=\"content-box-yellow\"><b>Cheat Sheet:<\/b> <a title=\"Free JPA 2.1 Cheat Sheet\" href=\"\/\/thorben-janssen.com\/free-jpa-2-1-cheat-sheet?source=content-box\">Get your free cheat sheet<\/a> with all features added in JPA 2.1 (incl. <i>function()<\/i>)<\/div>\n\n\n\n<p>Custom function calls in the WHERE part of the query work out of the box with Hibernate because it can guess the return type. But if you want to call the function in the SELECT part, like in the following code snippet, you have to register the function first.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted brush: java; gutter: true\">\nObject r = em.createQuery(&quot;SELECT function(&#039;calculate&#039;, a.id, 1) FROM Author a WHERE a.id = 1&quot;).getSingleResult();\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Register function in Hibernate dialect<\/h2>\n\n\n\n<p>One option to do this is to create a custom dialect. Hibernate&nbsp;provides specific dialects for most common databases to support database specific features, like functions, data types, and SQL dialects. Most database specific functions are already supported by the specific Hibernate dialect. So please have a look at it, before you try to register the function yourself.<\/p>\n\n\n\n<p>The definition of a custom function is not that difficult, as you can see in the following code snippet. You can extend an existing dialect and register your function in the constructor by calling the <a href=\"http:\/\/docs.jboss.org\/hibernate\/orm\/5.1\/javadocs\/org\/hibernate\/dialect\/Dialect.html#registerFunction-java.lang.String-org.hibernate.dialect.function.SQLFunction-\" rel=\"nofollow noopener\" target=\"_blank\"><em>registerFunction(String name, SQLFunction function)<\/em><\/a> method.<\/p>\n\n\n\n<p>I use a PostgreSQL database in this example and therefore extend the <em><a href=\"http:\/\/docs.jboss.org\/hibernate\/orm\/5.1\/javadocs\/org\/hibernate\/dialect\/PostgreSQL94Dialect.html\" rel=\"nofollow noopener\" target=\"_blank\">PostgreSQL94Dialect<\/a><\/em>, which already supports the database specific features. The only thing I have to do is to register my custom <em>calculate<\/em> function in the constructor. I register it as a\u00a0StandardSQLFunction which dynamically defines the return type based on the type of the first parameter.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted brush: java; gutter: true\">\npackage org.thoughts.on.java.db;\n\nimport org.hibernate.dialect.PostgreSQL94Dialect;\nimport org.hibernate.dialect.function.StandardSQLFunction;\n\npublic class MyPostgreSQL9Dialect extends PostgreSQL94Dialect {\n\n\tpublic MyPostgreSQL9Dialect() {\n\t\tsuper();\n\t\tregisterFunction(&quot;calculate&quot;, new StandardSQLFunction(&quot;calculate&quot;));\n\t}\n}\n<\/pre>\n\n\n\n<p>And then I have to reference the new dialect in the persistence.xml file.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted brush: xml; gutter: true\">\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;\n&lt;persistence xmlns=&quot;http:\/\/xmlns.jcp.org\/xml\/ns\/persistence&quot;\n\txmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot; version=&quot;2.1&quot;\n\txsi:schemaLocation=&quot;http:\/\/xmlns.jcp.org\/xml\/ns\/persistence http:\/\/xmlns.jcp.org\/xml\/ns\/persistence\/persistence_2_1.xsd&quot;&gt;\n\t&lt;persistence-unit name=&quot;my-persistence-unit&quot;&gt;\n\t\t&lt;description&gt;Custom Database Functions&lt;\/description&gt;\n\t\t&lt;provider&gt;org.hibernate.jpa.HibernatePersistenceProvider&lt;\/provider&gt;\n\t\t&lt;exclude-unlisted-classes&gt;false&lt;\/exclude-unlisted-classes&gt;\n\n\t\t&lt;properties&gt;\n\t\t  &lt;!-- use custom dialect --&gt;\n\t\t\t&lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.thoughts.on.java.db.MyPostgreSQL9Dialect&quot; \/&gt;\n\n      &lt;!-- define database connection --&gt;\n\t\t\t&lt;property name=&quot;javax.persistence.jdbc.driver&quot; value=&quot;org.postgresql.Driver&quot; \/&gt;\n\t\t\t&lt;property name=&quot;javax.persistence.jdbc.url&quot; value=&quot;jdbc:postgresql:\/\/localhost:5432\/HPT&quot; \/&gt;\n\t\t\t&lt;property name=&quot;javax.persistence.jdbc.user&quot; value=&quot;postgres&quot; \/&gt;\n\t\t\t&lt;property name=&quot;javax.persistence.jdbc.password&quot; value=&quot;postgres&quot; \/&gt;\n\t\t&lt;\/properties&gt;\n\t&lt;\/persistence-unit&gt;\n&lt;\/persistence&gt;\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>JPA 2.1 introduced the generic function <em>function()<\/em> to call any database function in a JPQL or Criteria query, even if the function is not directly supported by the JPA standard.<\/p>\n\n\n\n<p>If you use Hibernate as your JPA implementation, you have to also register the function in the dialect to use it in the SELECT part of the query. You therefore&nbsp;should extend an existing dialect for your specific database and register the additional functions in the constructor.<\/p>\n\n\n\n<p>If you want to learn more about the features introduced in JPA 2.1, have a look at&nbsp;<a title=\"JPA 2.1 \u2013 12 features every developer should know\" href=\"\/\/thorben-janssen.com\/jpa-21-overview\/\">JPA 2.1 \u2013 12 features every developer should know<\/a>&nbsp;and make sure to download the <a title=\"Free JPA 2.1 Cheat Sheet\" href=\"\/\/thorben-janssen.com\/free-jpa-2-1-cheat-sheet\/\">New Features in JPA 2.1<\/a> cheat sheet.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>JPA supports a set of database functions which you can use to perform small operations and transformations within a query. This is often easier and faster than doing it in the Java code. But how do you call functions which are not supported by the JPA standard, like database-specific ones or the custom functions implemented&#8230;<\/p>\n","protected":false},"author":14418,"featured_media":15060,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kad_blocks_custom_css":"","_kad_blocks_head_custom_js":"","_kad_blocks_body_custom_js":"","_kad_blocks_footer_custom_js":"","_kadence_starter_templates_imported_post":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"categories":[16,19,17],"tags":[33],"class_list":["post-1997","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-jpa","category-hibernate-performance","category-jpa2-1","tag-query"],"taxonomy_info":{"category":[{"value":16,"label":"JPA"},{"value":19,"label":"Hibernate Performance"},{"value":17,"label":"JPA2.1"}],"post_tag":[{"value":33,"label":"Query"}]},"featured_image_src_large":["https:\/\/thorben-janssen.com\/wp-content\/uploads\/2016\/04\/CustomDBfunctions.jpg",810,450,false],"author_info":{"display_name":"Thorben Janssen","author_link":"https:\/\/thorben-janssen.com\/author\/thorben-janssen\/"},"comment_info":9,"category_info":[{"term_id":16,"name":"JPA","slug":"jpa","term_group":0,"term_taxonomy_id":16,"taxonomy":"category","description":"","parent":0,"count":101,"filter":"raw","cat_ID":16,"category_count":101,"category_description":"","cat_name":"JPA","category_nicename":"jpa","category_parent":0},{"term_id":19,"name":"Hibernate Performance","slug":"hibernate-performance","term_group":0,"term_taxonomy_id":19,"taxonomy":"category","description":"","parent":9,"count":41,"filter":"raw","cat_ID":19,"category_count":41,"category_description":"","cat_name":"Hibernate Performance","category_nicename":"hibernate-performance","category_parent":9},{"term_id":17,"name":"JPA2.1","slug":"jpa2-1","term_group":0,"term_taxonomy_id":17,"taxonomy":"category","description":"","parent":0,"count":23,"filter":"raw","cat_ID":17,"category_count":23,"category_description":"","cat_name":"JPA2.1","category_nicename":"jpa2-1","category_parent":0}],"tag_info":[{"term_id":33,"name":"Query","slug":"query","term_group":0,"term_taxonomy_id":33,"taxonomy":"post_tag","description":"","parent":0,"count":103,"filter":"raw"}],"_links":{"self":[{"href":"https:\/\/thorben-janssen.com\/wp-json\/wp\/v2\/posts\/1997","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thorben-janssen.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thorben-janssen.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thorben-janssen.com\/wp-json\/wp\/v2\/users\/14418"}],"replies":[{"embeddable":true,"href":"https:\/\/thorben-janssen.com\/wp-json\/wp\/v2\/comments?post=1997"}],"version-history":[{"count":2,"href":"https:\/\/thorben-janssen.com\/wp-json\/wp\/v2\/posts\/1997\/revisions"}],"predecessor-version":[{"id":34031,"href":"https:\/\/thorben-janssen.com\/wp-json\/wp\/v2\/posts\/1997\/revisions\/34031"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thorben-janssen.com\/wp-json\/wp\/v2\/media\/15060"}],"wp:attachment":[{"href":"https:\/\/thorben-janssen.com\/wp-json\/wp\/v2\/media?parent=1997"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thorben-janssen.com\/wp-json\/wp\/v2\/categories?post=1997"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thorben-janssen.com\/wp-json\/wp\/v2\/tags?post=1997"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}