JPA + Hibernate - @NamedStoredProcedureQuery Example
February 09, 2023
On this page, we will learn to use Jakarta persistence @NamedStoredProcedureQuery
annotation in our Hibernate application.
1. The
@NamedStoredProcedureQuery
is used to run a stored procedure. It is used on an entity or mapped superclass.
2. The
@NamedStoredProcedureQuery
specifies and names a stored procedure, its parameters, and its result type.
3. The
@NamedStoredProcedureQueries
annotation is used to configure more than one @NamedStoredProcedureQuery
annotations.
4. Find a sample code to use
@NamedStoredProcedureQuery
.
@NamedStoredProcedureQueries({ @NamedStoredProcedureQuery( name = "myAddArticle", procedureName = "add_article", parameters = { @StoredProcedureParameter(name = "title", type = String.class, mode = ParameterMode.IN), @StoredProcedureParameter(name = "category", type = String.class, mode = ParameterMode.IN) } ), @NamedStoredProcedureQuery( name = "myReadArticle", procedureName = "read_article", parameters = { @StoredProcedureParameter(name = "id", type = Integer.class, mode = ParameterMode.IN), @StoredProcedureParameter(name = "title", type = String.class, mode = ParameterMode.OUT), @StoredProcedureParameter(name = "category", type = String.class, mode = ParameterMode.OUT) } ) }) @Entity() @Table(name = "articles") public class Article { ------ }
@NamedStoredProcedureQuery Elements
Find the@NamedStoredProcedureQuery
elements.
1. name : Required. The name is used to access the stored procedure in
EntityManager
methods such as
StoredProcedureQuery query = entityManager.createNamedStoredProcedureQuery("myReadArticle");
3. parameters : Optional. Information about all parameters of the stored procedure.
Note: All parameters must be defined in the same order in which they occur in the stored procedure.
Suppose we have a database stored procedure code snippet as given below.
CREATE PROCEDURE add_article ( IN in_title VARCHAR(100), IN in_category VARCHAR(100) )
parameters = { @StoredProcedureParameter(name = "title", type = String.class, mode = ParameterMode.IN), // for in_title @StoredProcedureParameter(name = "category", type = String.class, mode = ParameterMode.IN) // for in_category }
query.setParameter("title", "Stored Procedure in Hibernate"); query.setParameter("category", "Hibernate");
resultClasses = { Article.java }
6. hints : Query properties and hints.
ParameterMode
TheParameterMode
enum specifies the mode of a parameter of a stored procedure query. Find the constants of this enum.
IN : Stored procedure input parameter.
@StoredProcedureParameter( name = "id", type = Integer.class, mode = ParameterMode.IN )
@StoredProcedureParameter( name = "title", type = String.class, mode = ParameterMode.OUT )
@StoredProcedureParameter( name = "writer", type = String.class, mode = ParameterMode.INOUT )
@StoredProcedureParameter( name = "article_cursor", type = void.class, mode = ParameterMode.REF_CURSOR )
Complete Example
1. Technologies Used1. Java 19
2. Hibernate 6
3. Jakarta Persistence API 3
4. MySQL 5.5
2. MySQL Database
CREATE TABLE `articles` ( `article_id` INT(5) NOT NULL AUTO_INCREMENT, `title` VARCHAR(200) NOT NULL, `category` VARCHAR(100) NOT NULL, PRIMARY KEY (`article_id`) ) CREATE PROCEDURE read_article ( IN in_id INTEGER, OUT out_title VARCHAR(100), OUT out_category VARCHAR(100) ) BEGIN SELECT title, category INTO out_title, out_category FROM articles WHERE article_id = in_id; END; CREATE PROCEDURE add_article ( IN in_title VARCHAR(100), IN in_category VARCHAR(100) ) BEGIN INSERT INTO articles (title, category) values (in_title, in_category); END;
<dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>6.1.6.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>6.0.0.Alpha7</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.32</version> </dependency> </dependencies>
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" version="3.0"> <persistence-unit name="com.concretepage"> <description>Procedure Demo</description> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> <property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver" /> <property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost/concretepage" /> <property name="jakarta.persistence.jdbc.user" value="root" /> <property name="jakarta.persistence.jdbc.password" value="cp" /> </properties> </persistence-unit> </persistence>
HibernateUtil.java
package com.concretepage.util; import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; public class HibernateUtil { private static final EntityManagerFactory emFactory; static { emFactory = Persistence.createEntityManagerFactory("com.concretepage"); } public static EntityManager getEntityManager(){ return emFactory.createEntityManager(); } }
package com.concretepage.entity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.NamedStoredProcedureQueries; import jakarta.persistence.NamedStoredProcedureQuery; import jakarta.persistence.ParameterMode; import jakarta.persistence.StoredProcedureParameter; import jakarta.persistence.Table; @NamedStoredProcedureQueries({ @NamedStoredProcedureQuery( name = "myAddArticle", procedureName = "add_article", parameters = { @StoredProcedureParameter(name = "title", type = String.class, mode = ParameterMode.IN), // for in_title @StoredProcedureParameter(name = "category", type = String.class, mode = ParameterMode.IN) // for in_category } ), @NamedStoredProcedureQuery( name = "myReadArticle", procedureName = "read_article", parameters = { @StoredProcedureParameter(name = "id", type = Integer.class, mode = ParameterMode.IN), // for in_id @StoredProcedureParameter(name = "title", type = String.class, mode = ParameterMode.OUT), // for out_title @StoredProcedureParameter(name = "category", type = String.class, mode = ParameterMode.OUT) // for out_category } ) }) @Entity() @Table(name = "articles") public class Article { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "article_id") private int articleId; @Column(name = "title") private String title; @Column(name = "category") private String category; //setters and getters }
package com.concretepage; import com.concretepage.util.HibernateUtil; import jakarta.persistence.EntityManager; import jakarta.persistence.EntityTransaction; import jakarta.persistence.StoredProcedureQuery; public class RunProcedure { public static void main(String[] args) { // Run Stored procedure (add_article) EntityManager entityManager = HibernateUtil.getEntityManager(); StoredProcedureQuery query = entityManager.createNamedStoredProcedureQuery("myAddArticle"); query.setParameter("title", "Stored Procedure in Hibernate"); query.setParameter("category", "Hibernate"); EntityTransaction entityTransaction = entityManager.getTransaction(); entityTransaction.begin(); query.execute(); entityTransaction.commit(); // Run Stored procedure (read_article) query = entityManager.createNamedStoredProcedureQuery("myReadArticle"); query.setParameter("id", 1); query.execute(); String title = (String) query.getOutputParameterValue("title"); String cat = (String) query.getOutputParameterValue("category"); System.out.println(title); System.out.println(cat); } }
References
Annotation Type NamedStoredProcedureQueryHibernate ORM User Guide