diff --git a/persistence-jpa/pom.xml b/persistence-jpa/pom.xml
new file mode 100644
index 0000000000..a69ff72569
--- /dev/null
+++ b/persistence-jpa/pom.xml
@@ -0,0 +1,96 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ jpa-storedprocedure
+ 1.0
+ jar
+
+
+ 7.0
+ 11.2.0.4
+ 5.1.0.Final
+
+
+
+ JpaStoredProcedure
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.8
+ 1.8
+
+
+
+ maven-assembly-plugin
+
+
+
+ jar-with-dependencies
+
+
+
+
+
+
+
+
+
+
+
+ javax
+ javaee-api
+ ${jee.version}
+ provided
+
+
+
+ org.hibernate
+ hibernate-entitymanager
+ ${hibernate.version}
+
+
+
+
+ com.oracle
+ ojdbc6
+ ${oracle.version}
+
+
+
+
+ org.postgresql
+ postgresql
+ 9.4.1208
+
+
+
+
+
+ mysql
+ mysql-connector-java
+ 5.1.38
+
+
+
+
+
+ junit
+ junit
+ 4.4
+
+
+
+ commons-io
+ commons-io
+ 2.4
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-jpa/src/main/java/com/baeldung/jpa/model/Car.java b/persistence-jpa/src/main/java/com/baeldung/jpa/model/Car.java
new file mode 100644
index 0000000000..5fefb49660
--- /dev/null
+++ b/persistence-jpa/src/main/java/com/baeldung/jpa/model/Car.java
@@ -0,0 +1,60 @@
+package com.baeldung.jpa.model;
+
+import javax.persistence.*;
+
+/**
+ * Created by Giuseppe Bueti on 22/02/2016.
+ */
+
+@Entity
+@Table(name = "CAR")
+@NamedStoredProcedureQueries({
+ @NamedStoredProcedureQuery(name = "findByModelProcedure", procedureName = "FIND_CAR_BY_MODEL", resultClasses = { Car.class }, parameters = { @StoredProcedureParameter(name = "data", type = Car.class, mode = ParameterMode.REF_CURSOR),
+ @StoredProcedureParameter(name = "p_model", type = String.class, mode = ParameterMode.IN) }),
+ @NamedStoredProcedureQuery(name = "findByYearProcedure", procedureName = "FIND_CAR_BY_YEAR", resultClasses = { Car.class }, parameters = { @StoredProcedureParameter(name = "data", type = Car.class, mode = ParameterMode.REF_CURSOR),
+ @StoredProcedureParameter(name = "p_year", type = Integer.class, mode = ParameterMode.IN) }) })
+public class Car {
+
+ private long id;
+ private String model;
+ private Integer year;
+
+ public Car(String model, Integer year) {
+ this.model = model;
+ this.year = year;
+ }
+
+ public Car() {
+ }
+
+ @Id
+ @SequenceGenerator(name = "CarIdSequence", sequenceName = "SEQ_CAR_ID", allocationSize = 1)
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CarIdSequence")
+ //@GeneratedValue(strategy = GenerationType.IDENTITY) -- for MySQL
+ @Column(name = "ID", unique = true, nullable = false, scale = 0)
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ @Column(name = "MODEL")
+ public String getModel() {
+ return model;
+ }
+
+ public void setModel(String model) {
+ this.model = model;
+ }
+
+ @Column(name = "YEAR")
+ public Integer getYear() {
+ return year;
+ }
+
+ public void setYear(Integer year) {
+ this.year = year;
+ }
+}
diff --git a/persistence-jpa/src/main/java/com/baeldung/jpa/model/QueryParameter.java b/persistence-jpa/src/main/java/com/baeldung/jpa/model/QueryParameter.java
new file mode 100644
index 0000000000..326886842d
--- /dev/null
+++ b/persistence-jpa/src/main/java/com/baeldung/jpa/model/QueryParameter.java
@@ -0,0 +1,27 @@
+package com.baeldung.jpa.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class QueryParameter {
+
+ private Map parameters = null;
+
+ private QueryParameter(String name, Object value) {
+ this.parameters = new HashMap<>();
+ this.parameters.put(name, value);
+ }
+
+ public static QueryParameter with(String name, Object value) {
+ return new QueryParameter(name, value);
+ }
+
+ public QueryParameter and(String name, Object value) {
+ this.parameters.put(name, value);
+ return this;
+ }
+
+ public Map parameters() {
+ return this.parameters;
+ }
+}
\ No newline at end of file
diff --git a/persistence-jpa/src/main/resources/META-INF/persistence.xml b/persistence-jpa/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000000..3cb81fc9c1
--- /dev/null
+++ b/persistence-jpa/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,30 @@
+
+
+
+
+ org.hibernate.jpa.HibernatePersistenceProvider
+ com.baeldung.jpa.model.Car
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-jpa/src/main/resources/config/database/FindCarByYearProcedureMySQL.sql b/persistence-jpa/src/main/resources/config/database/FindCarByYearProcedureMySQL.sql
new file mode 100644
index 0000000000..0ef84fb7eb
--- /dev/null
+++ b/persistence-jpa/src/main/resources/config/database/FindCarByYearProcedureMySQL.sql
@@ -0,0 +1,8 @@
+DELIMITER $$
+CREATE DEFINER=`root`@`localhost` PROCEDURE `FIND_CAR_BY_YEAR`(in p_year int)
+begin
+SELECT ID, MODEL, YEAR
+ FROM CAR
+ WHERE YEAR = p_year;
+end$$
+DELIMITER ;
diff --git a/persistence-jpa/src/main/resources/config/database/FindCarByYearProcedureOracle.sql b/persistence-jpa/src/main/resources/config/database/FindCarByYearProcedureOracle.sql
new file mode 100644
index 0000000000..f9230aad42
--- /dev/null
+++ b/persistence-jpa/src/main/resources/config/database/FindCarByYearProcedureOracle.sql
@@ -0,0 +1,7 @@
+create or replace PROCEDURE FIND_CAR_BY_YEAR ( p_year IN NUMBER, data OUT SYS_REFCURSOR ) AS
+ BEGIN
+ OPEN data FOR
+ SELECT ID, MODEL, YEAR
+ FROM CAR
+ WHERE YEAR = p_year;
+ END FIND_CAR_BY_YEAR;
\ No newline at end of file
diff --git a/persistence-jpa/src/main/resources/config/database/create_database.sql b/persistence-jpa/src/main/resources/config/database/create_database.sql
new file mode 100644
index 0000000000..d84007b74d
--- /dev/null
+++ b/persistence-jpa/src/main/resources/config/database/create_database.sql
@@ -0,0 +1,34 @@
+CREATE TABLESPACE JPA DATAFILE 'C:\oraclexe\app\oracle\oradata\XE\JPA.DBF' SIZE 100M AUTOEXTEND ON MAXSIZE 2048M;
+
+--DROP USER JPA CASCADE;
+CREATE USER JPA IDENTIFIED BY JPA DEFAULT TABLESPACE JPA;
+ALTER USER JPA QUOTA UNLIMITED ON "JPA" ACCOUNT UNLOCK;
+
+GRANT CREATE SESSION TO "JPA";
+GRANT ALTER SESSION TO "JPA";
+GRANT CREATE TABLE TO "JPA";
+GRANT CREATE TRIGGER TO "JPA";
+GRANT CREATE VIEW TO "JPA";
+GRANT CREATE DIMENSION TO "JPA";
+GRANT CREATE CLUSTER TO "JPA";
+GRANT CREATE INDEXTYPE TO "JPA";
+GRANT CREATE ROLE TO "JPA";
+GRANT CREATE SEQUENCE TO "JPA";
+GRANT CREATE TYPE TO "JPA";
+GRANT CREATE MATERIALIZED VIEW TO "JPA";
+GRANT CREATE PROCEDURE TO "JPA";
+GRANT CREATE SYNONYM TO "JPA";
+
+CREATE SEQUENCE SEQ_CAR_ID INCREMENT BY 1 START WITH 1 MAXVALUE 999999999999999 MINVALUE 1;
+
+CREATE TABLE CAR
+(
+ ID NUMBER NOT NULL,
+ MODEL VARCHAR2(50) NOT NULL,
+ YEAR NUMBER(4) NOT NULL
+);
+
+ALTER TABLE CAR ADD CONSTRAINT CAR_PK PRIMARY KEY ( ID );
+
+commit;
+
diff --git a/persistence-jpa/src/main/resources/config/database/create_table_mysql.sql b/persistence-jpa/src/main/resources/config/database/create_table_mysql.sql
new file mode 100644
index 0000000000..4a4feebdea
--- /dev/null
+++ b/persistence-jpa/src/main/resources/config/database/create_table_mysql.sql
@@ -0,0 +1,6 @@
+CREATE TABLE `car` (
+ `ID` int(10) NOT NULL AUTO_INCREMENT,
+ `MODEL` varchar(50) NOT NULL,
+ `YEAR` int(4) NOT NULL,
+ PRIMARY KEY (`ID`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
\ No newline at end of file
diff --git a/persistence-jpa/src/main/resources/config/database/insert_cars.sql b/persistence-jpa/src/main/resources/config/database/insert_cars.sql
new file mode 100644
index 0000000000..4879ffc79e
--- /dev/null
+++ b/persistence-jpa/src/main/resources/config/database/insert_cars.sql
@@ -0,0 +1,5 @@
+INSERT INTO CAR (ID, MODEL, YEAR) VALUES ('123456', 'Camaro', '2012');
+INSERT INTO "JPA"."CAR" (ID, MODEL, YEAR) VALUES ('12112', 'Fiat Panda', '2000');
+INSERT INTO "JPA"."CAR" (ID, MODEL, YEAR) VALUES ('111000', 'Fiat Punto', '2007');
+INSERT INTO "JPA"."CAR" (ID, MODEL, YEAR) VALUES ('3382', 'Citroen C3', '2009');
+commit;
\ No newline at end of file
diff --git a/persistence-jpa/src/test/java/com/baeldung/jpa/storedprocedure/StoredProcedureTest.java b/persistence-jpa/src/test/java/com/baeldung/jpa/storedprocedure/StoredProcedureTest.java
new file mode 100644
index 0000000000..67f8eb4304
--- /dev/null
+++ b/persistence-jpa/src/test/java/com/baeldung/jpa/storedprocedure/StoredProcedureTest.java
@@ -0,0 +1,85 @@
+package com.baeldung.jpa.storedprocedure;
+
+import com.baeldung.jpa.model.Car;
+import org.junit.*;
+
+import javax.persistence.*;
+
+/**
+ * Created by Giuseppe Bueti on 23/02/2016.
+ */
+public class StoredProcedureTest {
+
+ private static EntityManagerFactory factory = null;
+ private static EntityManager entityManager = null;
+
+ @BeforeClass
+ public static void init() {
+ factory = Persistence.createEntityManagerFactory("jpa-db");
+ entityManager = factory.createEntityManager();
+ }
+
+ @Before
+ public void setup() {
+ }
+
+ @Test
+ public void createCarTest() {
+ EntityTransaction transaction = entityManager.getTransaction();
+ try {
+ transaction.begin();
+ Car car = new Car("Fiat Punto", 2015);
+ entityManager.persist(car);
+ transaction.commit();
+ } catch (Exception e) {
+ System.out.println(e.getCause());
+ if (transaction.isActive()) {
+ transaction.rollback();
+ }
+ }
+ }
+
+ @Test
+ public void findCarsByYear() {
+ final StoredProcedureQuery findByYearProcedure = entityManager.createNamedStoredProcedureQuery("findByYearProcedure");
+ StoredProcedureQuery storedProcedure = findByYearProcedure.setParameter("p_year", 2015);
+ storedProcedure.getResultList().forEach(c -> Assert.assertEquals(new Integer(2015), ((Car) c).getYear()));
+ }
+
+ @Test
+ public void findCarsByModel() {
+ final StoredProcedureQuery findByModelProcedure = entityManager.createNamedStoredProcedureQuery("findByModelProcedure");
+ StoredProcedureQuery storedProcedure = findByModelProcedure.setParameter("p_model", "Camaro");
+ storedProcedure.getResultList().forEach(c -> Assert.assertEquals("Camaro", ((Car) c).getModel()));
+ }
+
+ @Test
+ public void findCarsByYearNoNamedStored() {
+ StoredProcedureQuery findByYearProcedure =
+ entityManager.createStoredProcedureQuery("FIND_CAR_BY_YEAR", Car.class)
+ .registerStoredProcedureParameter("data", Void.class, ParameterMode.REF_CURSOR)
+ .registerStoredProcedureParameter("p_year", Integer.class, ParameterMode.IN)
+ .setParameter("p_year", 2015);
+
+ findByYearProcedure.getResultList().forEach(c -> Assert.assertEquals(new Integer(2015), ((Car) c).getYear()));
+ }
+
+ @Test @Ignore
+ public void findCarsByYearMySql() {
+ StoredProcedureQuery storedProcedure = entityManager.createStoredProcedureQuery("FIND_CAR_BY_YEAR",Car.class)
+ .registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN)
+ .setParameter(1, 2015);
+ storedProcedure.getResultList().forEach(c -> Assert.assertEquals(new Integer(2015), ((Car) c).getYear()));
+ }
+
+ @AfterClass
+ public static void destroy() {
+
+ if (entityManager != null) {
+ entityManager.close();
+ }
+ if (factory != null) {
+ factory.close();
+ }
+ }
+}
diff --git a/persistence-jpa/src/test/resources/persistence.xml b/persistence-jpa/src/test/resources/persistence.xml
new file mode 100644
index 0000000000..d118a264d3
--- /dev/null
+++ b/persistence-jpa/src/test/resources/persistence.xml
@@ -0,0 +1,31 @@
+
+
+
+
+ org.hibernate.jpa.HibernatePersistenceProvider
+ com.baeldung.jpa.model.Car
+
+
+
+
+
+
+
+
+
+
+
+
+
+