Calling stored procedure in Hibernate using Annotation
Third approach to call DB stored procedure in hibernate
By Calling getNamedQuery() method with the use of Annotation:-
Steps for creating example to call a stored procedure using Native SQL in Hibernate:-
- At first, create a java project using eclipse and name it as StoredProcCallUsingHibernate.
- Inside src folder, create a package named com.gaurav.hibernate.beans.
- After that, create a java bean file named StudentAnnotatedBean and place the below corresponding code in that file.
- Now, Inside src folder create hibernate.cfg.xml file and place the below corresponding source code.
- Now, in src folder, create a package com.gaurav.hibernate.procedurecall and place the ProcCallByNamedNativeQuery.java client program in that package which is available below.
- Create the Student table and insert the records in the database, then create the corresponding stored procedure which we are going to call using Hibernate
Note: If we are using annotations then in this case hibernate mapping file is not required.
Table Structure and Insert queries are available below:-
DROP TABLE IF EXISTS student;
CREATE TABLE student (
STUDENT_ID decimal(20,0) DEFAULT NULL,
FIRSTNAME varchar(50) NOT NULL,
LASTNAME varchar(50) NOT NULL,
BIRTHDATE date DEFAULT NULL,
TOTAL_MARKS decimal(20,0) DEFAULT NULL,
DIVISION varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*Data for the table student */
insert into student (STUDENT_ID,FIRSTNAME,LASTNAME,BIRTHDATE,TOTAL_MARKS,DIVISION) values ('1','Kumar','Gaurav','1978-05-12','920','FIRST');
insert into student (STUDENT_ID,FIRSTNAME,LASTNAME,BIRTHDATE,TOTAL_MARKS,DIVISION) values ('2','Gaurav','Kumar','1980-11-19','880','FIRST');
insert into student (STUDENT_ID,FIRSTNAME,LASTNAME,BIRTHDATE,TOTAL_MARKS,DIVISION) values ('3','Shivam','Kumar','1989-07-11','670','SECOND');
getStudentDetails() stored procedure. Below is the syntax for MySQL DB
DELIMITER $$
DROP PROCEDURE IF EXISTS test.getStudentDetails $$
CREATE PROCEDURE test.getStudentDetails
(IN STUD_ID INT)
BEGIN
SELECT *
FROM STUDENT
WHERE STUDENT_ID = STUD_ID;
END $$
DELIMITER ;
Below is the initial table status, after the table creation and record insertion:-
StudentAnnotatedBean.java
package com.gaurav.hibernate.beans;
import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.NamedNativeQuery;
import javax.persistence.Table;
@Entity
@Table(name="STUDENT")
@NamedNativeQuery(
name = "call_GetStudentDetails_procedure",
query = "CALL getStudentDetails(:studId)",
resultClass = StudentAnnotatedBean.class
)
public class StudentAnnotatedBean implements java.io.Serializable{
/**
*
*/
private static final long serialVersionUID = 5282962375876751766L;
private int studentId;
private String firstName;
private String lastName;
private Date birthDate;
private int totalMarks;
private String division;
/**
* @return the studentId
*/
@Id
@Column(name="STUDENT_ID")
public int getStudentId() {
return studentId;
}
/**
* @param studentId
* the studentId to set
*/
public void setStudentId(int studentId) {
this.studentId = studentId;
}
/**
* @return the firstName
*/
@Column(name="FIRSTNAME")
public String getFirstName() {
return firstName;
}
/**
* @param firstName
* the firstName to set
*/
public void setFirstName(String firstName) {
this.firstName = firstName;
}
/**
* @return the lastName
*/
@Column(name="LASTNAME")
public String getLastName() {
return lastName;
}
/**
* @param lastName
* the lastName to set
*/
public void setLastName(String lastName) {
this.lastName = lastName;
}
/**
* @return the birthDate
*/
@Column(name="BIRTHDATE")
public Date getBirthDate() {
return birthDate;
}
/**
* @param birthDate
* the birthDate to set
*/
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
/**
* @return the totalMarks
*/
@Column(name="TOTAL_MARKS")
public int getTotalMarks() {
return totalMarks;
}
/**
* @param totalMarks
* the totalMarks to set
*/
public void setTotalMarks(int totalMarks) {
this.totalMarks = totalMarks;
}
/**
* @return the division
*/
@Column(name="DIVISION")
public String getDivision() {
return division;
}
/**
* @param division
* the division to set
*/
public void setDivision(String division) {
this.division = division;
}
}
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="hibernate.connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.pool_size">1</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<!-- <mapping class="com.gaurav.hibernate.beans.StudentAnnotatedBean"/> -->
</session-factory>
</hibernate-configuration>
ProcCallByNamedNativeQuery.java
package com.gaurav.hibernate.procedurecall;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import com.gaurav.hibernate.beans.StudentAnnotatedBean;
public class ProcCallByNamedNativeQuery {
private static Session session = null;
@SuppressWarnings("unchecked")
public static List<StudentAnnotatedBean> retrieveStudentAnnotatedBean(
int stud_id) {
/**
* This is the use of Named Native SQL Query – getNamedQuery, another
* way to call a stored procedure using Native SQL.
*/
Query query = session.getNamedQuery("call_GetStudentDetails_procedure")
.setParameter("studId", stud_id);
List<StudentAnnotatedBean> studentAnnotatedBeanList = query.list();
return studentAnnotatedBeanList;
}
public static void main(String[] args) {
try {
/**
* If we are using Annotated classes then we have two way to get SessionFactory object
First Approach Using Annotation:-
1. We can create sessionFactory object like below :-
SessionFactory sessionFactory = new AnnotationConfiguration().configure() .buildSessionFactory();
2. We have to add below entry in hibernate configuration file for annotated class mapping
<mapping class="package_name.annotated_classname"/>
Second approach Using Annotation:-
1. We need to create an instance of AnnotationConfiguration class like below :-
AnnotationConfiguration annotationConfiguration = new AnnotationConfiguration();
2. We have to call addAnnotatedClass() method on AnnotationConfiguration object and we need to pass
the annotated class name.
3. Then using AnnotationConfiguration class object we need to call buildSessionFactory()
for getting SessionFactory object.
annotationConfiguration.configure().buildSessionFactory();
Below I am using second approach. First approach i have commented and even commented entry is also available in configuration file in order to follow first approach.
*/
/*
* SessionFactory sessionFactory = new
* AnnotationConfiguration().configure().buildSessionFactory();
*/
AnnotationConfiguration annotationConfiguration = new AnnotationConfiguration();
annotationConfiguration
.addAnnotatedClass(StudentAnnotatedBean.class);
SessionFactory sessionFactory = annotationConfiguration.configure()
.buildSessionFactory();
session = sessionFactory.openSession();
System.out.print("Procedure Invocation completed :- ");
List<StudentAnnotatedBean> studentDataInList = retrieveStudentAnnotatedBean(2);
if (studentDataInList != null) {
for (StudentAnnotatedBean studentAnnotatedBean : studentDataInList) {
System.out.println("FIRSTNAME :- "
+ studentAnnotatedBean.getFirstName());
System.out.println("LASTNAME :- "
+ studentAnnotatedBean.getLastName());
System.out.println("BIRTHDATE :- "
+ studentAnnotatedBean.getBirthDate());
System.out.println("TOTAL MARKS :- "
+ studentAnnotatedBean.getTotalMarks());
System.out.println("DIVISION :- "
+ studentAnnotatedBean.getDivision());
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
session.flush();
session.close();
}
}
}
Below you can find the complete project structure in eclipse:-
Result:-
Required Jars for this application is as below:-
antlr-2.7.6.jar
asm-2.2.2.jar
asm-commons-2.2.2.jar
cglib-nodep-2.1_3.jar
commons-collections.jar
commons-logging.jar
dom4j-1.6.1.jar
ehcache-1.1.jar
ejb3-persistence.jar
hibernate-annotations.jar
hibernate-commons-annotations.jar
hibernate3.jar
jta.jar
log4j-1.2.14.jar
mysql-connector-java-5.0.4-bin.jar
java.sql.SQLException: Cannot perform fetch on a PLSQL statement: next. Getting this error when i calling SP from Hibernate
ReplyDeleteI follow steps given by you to call stored procedures from hibernate but am getting following exception.
ReplyDeleteERROR: Cannot perform fetch on a PLSQL statement: next
Can you please help me to get the solution for this.
Check your In-Out parameter of your procedure, then accordingly proceed, you will be able to resolve this.
DeleteHello sir,
DeleteI am trying to execute procedure which takes only input parameters.
with following code
Query query = SQLFactory.getSession().getNamedQuery("callRegistrationProcedure").setParameter("regID", id).setParameter("lName", lName);
It does not return anything from database,I just want to update the input values in the database.
Can you please help me how i can pass multiple parameters to store procedure?
I am using ORACLE 11g as my database.Above code run fine with MYSQL database but what if am run it with ORACLE 11g DB
ReplyDeleteThis will work fine for other DB also, Only the thing is DB configuration will get changed in Hibernate configuration file and the corresponding dependent jars for oracle.
DeleteI used Oracle 11g and followed all the procedures but here is my error: I am running on the latest hibernate...
ReplyDeleteProcedure Invocation completed :- Hibernate: CALL getStudentDetails(?)
Oct 11, 2015 9:37:18 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 6576, SQLState: 65000
Oct 11, 2015 9:37:18 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: ORA-06576: not a valid function or procedure name
org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:123)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:91)
at org.hibernate.loader.Loader.getResultSet(Loader.java:2066)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1863)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1839)
at org.hibernate.loader.Loader.doQuery(Loader.java:910)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:355)
at org.hibernate.loader.Loader.doList(Loader.java:2554)
at org.hibernate.loader.Loader.doList(Loader.java:2540)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2370)
at org.hibernate.loader.Loader.list(Loader.java:2365)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:353)
at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1909)
at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:311)
at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:141)
at com.gaurav.hibernate.procedurecall.ProcCallByNamedNativeQuery.retrieveStudentAnnotatedBean(ProcCallByNamedNativeQuery.java:28)
at com.gaurav.hibernate.procedurecall.ProcCallByNamedNativeQuery.main(ProcCallByNamedNativeQuery.java:69)
Caused by: java.sql.SQLException: ORA-06576: not a valid function or procedure name
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:440)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:837)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:445)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:191)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:523)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1010)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1315)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3576)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3620)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1491)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:82)
... 15 more