how to call stored procedures in hibernate with date parameters? - java

MyController.java
#RequestMapping(value = "/ohlc",method = RequestMethod.POST)
public #ResponseBody List<OhlcResponse> getOhlc(#RequestBody OhlcRequest ohlcRequest) {
List<OhlcResponse> ohlc = ohlcService.getOhlc(ohlcRequest);
return ohlc;
}
OhlcDaoImpl.java
Query query = session.createSQLQuery(
"CALL uspGetOhlcData(:stockCode,:fromDate,:toDate)")
.addEntity(OhlcResponse.class)
.setParameter("stockCode", ohlcRequest.getStockSymbol())
.setParameter("fromDate",ohlcRequest.getFromDate())
.setParameter("toDate", ohlcRequest.getToDate());
List<OhlcResponse> list = query.list();
return list;
}
OhlcResponse.java
public class OhlcResponse {
private int Id;
private BigDecimal MaxPrice;
private BigDecimal MinPrice;
private BigDecimal PreviousClosingPrice;
private BigDecimal ClosingPrice;
public BigDecimal getMaxPrice() {
return MaxPrice;
}
public void setMaxPrice(BigDecimal maxPrice) {
MaxPrice = maxPrice;
}
public BigDecimal getMinPrice() {
return MinPrice;
}
public void setMinPrice(BigDecimal minPrice) {
MinPrice = minPrice;
}
public BigDecimal getPreviousClosingPrice() {
return PreviousClosingPrice;
}
public void setPreviousClosingPrice(BigDecimal previousClosingPrice) {
PreviousClosingPrice = previousClosingPrice;
}
public BigDecimal getClosingPrice() {
return ClosingPrice;
}
public void setClosingPrice(BigDecimal closingPrice) {
ClosingPrice = closingPrice;
}
Stored Procedure: uspGetOhlcData
CREATE PROCEDURE uspGetOhlcData
#StockSymbol varchar(50),
#fromDate date,
#toDate date
AS
BEGIN
SELECT spd.ClosingPrice, spd.PreviousClosingPrice, spd.MinPrice, spd.MaxPrice
FROM StockPriceDetl spd
inner join Stock stk on stk.Id = spd.StockId
inner join StockPriceMast spm on spm.Id = spd.MastId
WHERE stk.StockSymbol= #StockSymbol AND spm.TranDate Between #fromDate and #toDate
END
GO
as you can see my stored procedure returns maxprice, minprice, previousClosingPrice and ClosingPrice. i want to return those 4 data in json form binding them into ohlcResponse class.
the error i am currently getting is incorrect syntax near #PO

For syntax errors, your request and response seems ok,
Query query = session.createSQLQuery(
"CALL uspGetOhlcData(:stockCode,:fromDate,:toDate)")
You are using this query, and referring it the same in stored procedure as Symbol StockSymbol.
Try using stockCode here in Stored Procedure: uspGetOhlcData
CREATE PROCEDURE uspGetOhlcData
#stockCode varchar(50),
#fromDate date,
#toDate date
AS
BEGIN
SELECT spd.ClosingPrice, spd.PreviousClosingPrice, spd.MinPrice, spd.MaxPrice
FROM StockPriceDetl spd
inner join Stock stk on stk.Id = spd.StockId
inner join StockPriceMast spm on spm.Id = spd.MastId
WHERE stk.StockSymbol= #stockCode AND spm.TranDate Between #fromDate and #toDate
END
GO

Related

How to map a native query to POJO class using jpa and hibernate

I am using both JPA and hibernate in my project.
I have created a query in which i made join operation on many tables. So I created a native one. The results that i get are in a list of object[] but i would like the results to be converted automatically to a java POJO class.
You can check both the query syntax and POJO java class below.
JPA Query
#Query(value = "SELECT obsp.Identifier, obs.phenomenontimestart, nv.value " +
"From Series s " +
"INNER JOIN Featureofinterest fi on s.featureofinterestid = fi.featureofinterestid " +
"INNER JOIN ObservableProperty obsp on s.observablepropertyid = obsp.ObservablePropertyId " +
"INNER JOIN Observation obs on s.seriesid = obs.seriesid " +
"INNER JOIN NumericValue nv on nv.observationid = obs.observationid " +
"where fi.identifier = ?1 and obs.phenomenontimestart >= ?2 AND obs.phenomenontimestart <= ?3 " +
"order by obs.phenomenontimestart",
nativeQuery = true)
List<CurrentMeasure> findCurrentMeasure(String ident, Timestamp t1, Timestamp t2);
POJO class
public class CurrentMeasure {
private String identifier;
private Timestamp dateTime;
private BigDecimal bigDecimal;
public CurrentMeasure() {
}
public CurrentMeasure(String identifier, Timestamp dateTime, BigDecimal bigDecimal) {
this.identifier = identifier;
this.dateTime = dateTime;
this.bigDecimal = bigDecimal;
}
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public Timestamp getDateTime() {
return dateTime;
}
public void setDateTime(Timestamp dateTime) {
this.dateTime = dateTime;
}
public BigDecimal getBigDecimal() {
return bigDecimal;
}
public void setBigDecimal(BigDecimal bigDecimal) {
this.bigDecimal = bigDecimal;
}
}
With JPA you can call the constructor of your class CurrentMeasure directly inside your HQL query.
Example :
SELECT NEW <package>.CurrentMeasure(obsp.Identifier, obs.phenomenontimestart, nv.value) FROM ...
The NEW syntax is explained in Jboss documentation at chapter 11.5.
Another solution would be using HQL Transformers to achieve the same result without resorting to a constructor.

Stored procedure doesn't return a resultset

I'm trying to fetch data using this stored procedure:
create procedure Proc_Member_Statement #Counter int,#TransDate datetime
as
declare #schemeNo int,#MemberNo int
select #schemeNo = SchemeNo,#MemberNo = MemberNo from Members where Counter = #Counter
exec Individualize #schemeNo,#MemberNo,#TransDate,0,0
exec RepMemberCertificate_DBN_One #schemeNo,#MemberNo,#TransDate,0
My model class:
#NamedStoredProcedureQueries(
{
#NamedStoredProcedureQuery(
name = "getMemberStatement",
procedureName = "Proc_Member_Statement",
resultClasses = AccountStatement.class,
parameters = {
#StoredProcedureParameter(
name = "Counter",
mode = ParameterMode.IN,
type = Long.class
),
#StoredProcedureParameter(
name = "TransDate",
mode = ParameterMode.IN,
type = Date.class
)
}
),
}
)
#Entity
public class AccountStatement implements Serializable {
#Id
BigDecimal EmpOpBal;
public BigDecimal getEmpOpBal() {
return EmpOpBal;
}
public void setEmpOpBal(BigDecimal empOpBal) {
EmpOpBal = empOpBal;
}
public BigDecimal getEmprOpBal() {
return EmprOpBal;
}
public void setEmprOpBal(BigDecimal emprOpBal) {
EmprOpBal = emprOpBal;
}
public BigDecimal getEmpCont() {
return EmpCont;
}
public void setEmpCont(BigDecimal empCont) {
EmpCont = empCont;
}
public BigDecimal getEmprCont() {
return EmprCont;
}
public void setEmprCont(BigDecimal emprCont) {
EmprCont = emprCont;
}
public BigDecimal getEmpVolCont() {
return EmpVolCont;
}
public void setEmpVolCont(BigDecimal empVolCont) {
EmpVolCont = empVolCont;
}
public BigDecimal getEmprVolCont() {
return EmprVolCont;
}
public void setEmprVolCont(BigDecimal emprVolCont) {
EmprVolCont = emprVolCont;
}
public BigDecimal getEmpInt() {
return EmpInt;
}
public void setEmpInt(BigDecimal empInt) {
EmpInt = empInt;
}
public BigDecimal getEmprInt() {
return EmprInt;
}
public void setEmprInt(BigDecimal emprInt) {
EmprInt = emprInt;
}
public BigDecimal getClosingBal() {
return ClosingBal;
}
public void setClosingBal(BigDecimal closingBal) {
ClosingBal = closingBal;
}
public BigDecimal getEmpCBal() {
return EmpCBal;
}
public void setEmpCBal(BigDecimal empCBal) {
EmpCBal = empCBal;
}
public BigDecimal getEmprCBal() {
return EmprCBal;
}
public void setEmprCBal(BigDecimal emprCBal) {
EmprCBal = emprCBal;
}
#Id
BigDecimal EmprOpBal; // Employer Opening Balance
#Id
BigDecimal EmpCont; //Reg Employee
#Id
BigDecimal EmprCont; //Reg Employer
#Id
BigDecimal EmpVolCont; //Employee AVC
#Id
BigDecimal EmprVolCont; //Employer AVC
#Id
BigDecimal EmpInt; //Employee Interest
#Id
BigDecimal EmprInt; //Employer Interest
#Id
BigDecimal ClosingBal; //Closing Balance (Total)
#Id
BigDecimal EmpCBal; // Employee Closing Balance
#Id
BigDecimal EmprCBal; // Employer Closing Balance
}
Now when I try to run the stored procedure so I can get values from the database, I keep getting this error:
[java.lang.IllegalStateException: Current CallableStatement ou was not a ResultSet, but getResultList was called]
Here is the bean class:
public List<AccountStatement> getOpeningBalances(long memberId, Date date) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, -3);
jLogger.i("Calender >>>>> " + cal.getTime());
StoredProcedureQuery query = this.entityManager.createNamedStoredProcedureQuery("getMemberStatement");
query.setParameter("Counter", memberId);
query.setParameter("TransDate", cal.getTime());
query.execute();
try {
jLogger.i("Returned result >>>>>>>>>> " + query.getResultList());
List<AccountStatement> openingBalances = query.getResultList();
return openingBalances;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
What I'm i doing wrong?
EDIT:
Here is part of the output when I run the stored procedure in Microsoft SQL Server Management Studio:
I intend to use data from some of the columns within the system.
Thanks.
It's still not clear where the resultset you're expecting is coming from, I suspect from one of the stored procedures that's called within Proc_Member_Statement.
In order to get the results set out of Proc_Member_Statement you will need to insert the result set from the stored proc into a temporary table, and then at the end of Proc_Member_Statement SELECT the rows from it.

avoiding distinct keyword in batch query

Using Eclipselink 2.4.1, I'm trying to avoid the "distinct" keyword from appearing in batch queries. Documentation suggests that when using batch type EXISTS the distinct keyword isn't used, however in my experience it's used in all cases when retrieving a many-to-one relationship. For example, I have the following classes written against the SCOTT demo schema in oracle:
#Entity
public class Emp implements Serializable {
#Id private long empno;
private String ename;
#ManyToOne
#JoinColumn(name="DEPTNO")
private Dept dept;
public Emp() { }
public long getEmpno() { return this.empno; }
public void setEmpno(long empno) { this.empno = empno; }
public String getEname() { return this.ename; }
public void setEname(String ename) { this.ename = ename; }
public Dept getDept() { return this.dept; }
public void setDept(Dept dept) { this.dept = dept; }
}
#Entity
public class Dept implements Serializable {
#Id private long deptno;
private String dname;
public Dept() {}
public long getDeptno() { return this.deptno; }
public void setDeptno(long deptno) { this.deptno = deptno; }
public String getDname() { return this.dname; }
public void setDname(String dname) { this.dname = dname; }
}
I'm attempting to retrieve the employees and departments via batch fetch:
Query query = em.createQuery("select emp from Emp as emp ");
query.setHint(QueryHints.BATCH_TYPE, BatchFetchType.EXISTS);
query.setHint(QueryHints.BATCH, "emp.dept");
List<Emp> resultList = query.getResultList();
resultList.get(0).getDept();
The following SQL is generated:
[EL Fine]: sql: 2012-12-12 17:04:21.178--ServerSession(1034011695)--Connection(312759349)--SELECT EMPNO, ENAME, DEPTNO FROM SCOTT.EMP
[EL Fine]: sql: 2012-12-12 17:04:21.286--ServerSession(1034011695)--Connection(312759349)--SELECT distinct t0.DEPTNO, t0.DNAME FROM SCOTT.DEPT t0 WHERE EXISTS (SELECT t1.EMPNO FROM SCOTT.EMP t1 WHERE (t0.DEPTNO = t1.DEPTNO))
Is there something additional that needs to be done in addition to using EXISTS batch type to avoid the distinct keyword in batch queries?
Please log a bug. It should only be using this for JOIN batching.
You can set distinct to false on the query to avoid it. (there is no hint, you need to call dontUseDistinct() on the root ObjectLevelReadQuery).
((ObjectLevelReadQuery)((JpaQuery)query).getDatabaseQuery()).dontUseDistinct();

Hibernate Criteria Query with Group By and aliasToBean

I have table /entity called SaleRecord with fields such as
#Entity
public class SaleRecord {
private Long id;
private String type;
private Double amount;
//Getter and Setter and more fields
}
I want to write below query using Criteria
SELECT s.type AS accountName, SUM(s.amount) AS amount
FROM salerecord s
GROUP BY s.type
I have written using plain SQL in Hibernate as (Its working)
String sql = " SELECT s.type AS accountName, SUM(s.amount) AS amount ";
sql += " FROM salerecord s ";
sql += " GROUP BY s.type ";
List<CollectionDO> incomeList = (List<CollectionDO>) getSession().createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(CollectionDO.class)).list();
CollectionDO is another POJO class in which I want to populate the result.
But want to write using criteria, So how to write this query and transform result into CollectionDO class.
I have tried following but not working
Criteria criteria = getSession().createCriteria(SaleRecord.class).setResultTransformer(Transformers.aliasToBean(CollectionDO.class));
criteria.setProjection(Projections.property("type"));
criteria.setProjection(Projections.sum("amount"));
criteria.setProjection(Projections.groupProperty("type"));
return (List<CollectionDO>) criteria.list();
CollectionDO.java
public class CollectionDO {
private Double amount;
private String accountName;
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public Double getAmount() {
return amount;
}
public void setAmount(Double amount) {
this.amount = amount;
}
}
I think it is not able to Transform. as in Criteria column name is "type" but CollectionDO.java has field as "accountName"
Try it as follows (using this version of add to specify the alias name):
Criteria criteria =
getSession()
.createCriteria(SaleRecord.class)
.add(Restrictions.between("date",
reportForm.getFromDate(),
reportForm.getToDate()));
.setProjection(Projections.projectionList()
.add(Projections.property("type"), "accountName")
.add(Projections.sum("amount"))
.add(Projections.groupProperty("type")));
.setResultTransformer(Transformers.aliasToBean(CollectionDO.class))
return (List<CollectionDO>) criteria.list();

use of entityManager.createNativeQuery(query,foo.class)

I would like to return a List of Integers from a
javax.persistence.EntityManager.createNativeQuery call
Why is the following incorrect?
entityManager.createNativeQuery("Select P.AppID From P", Integer.class);
specifically why do I get "...Unknown entity: java.lang.Integer"
Would I have to create an entity class that has a single field that is an Integer ?
Thanks
What you do is called a projection. That's when you return only a scalar value that belongs to one entity. You can do this with JPA. See scalar value.
I think in this case, omitting the entity type altogether is possible:
Query query = em.createNativeQuery( "select id from users where username = ?");
query.setParameter(1, "lt");
BigDecimal val = (BigDecimal) query.getSingleResult();
Example taken from here.
That doesn't work because the second parameter should be a mapped entity and of course Integer is not a persistent class (since it doesn't have the #Entity annotation on it).
for you you should do the following:
Query q = em.createNativeQuery("select id from users where username = :username");
q.setParameter("username", "lt");
List<BigDecimal> values = q.getResultList();
or if you want to use HQL you can do something like this:
Query q = em.createQuery("select new Integer(id) from users where username = :username");
q.setParameter("username", "lt");
List<Integer> values = q.getResultList();
Regards.
Here is a DB2 Stored Procidure that receive a parameter
SQL
CREATE PROCEDURE getStateByName (IN StateName VARCHAR(128))
DYNAMIC RESULT SETS 1
P1: BEGIN
-- Declare cursor
DECLARE State_Cursor CURSOR WITH RETURN for
-- #######################################################################
-- # Replace the SQL statement with your statement.
-- # Note: Be sure to end statements with the terminator character (usually ';')
-- #
-- # The example SQL statement SELECT NAME FROM SYSIBM.SYSTABLES
-- # returns all names from SYSIBM.SYSTABLES.
-- ######################################################################
SELECT * FROM COUNTRY.STATE
WHERE PROVINCE_NAME LIKE UPPER(stateName);
-- Cursor left open for client application
OPEN Province_Cursor;
END P1
Java
//Country is a db2 scheme
//Now here is a java Entity bean Method
public List<Province> getStateByName(String stateName) throws Exception {
EntityManager em = this.em;
List<State> states= null;
try {
Query query = em.createNativeQuery("call NGB.getStateByName(?1)", Province.class);
query.setParameter(1, provinceName);
states= (List<Province>) query.getResultList();
} catch (Exception ex) {
throw ex;
}
return states;
}
Suppose your query is "select id,name from users where rollNo = 1001".
Here query will return a object with id and name column.
Your Response class is like bellow:
public class UserObject{
int id;
String name;
String rollNo;
public UserObject(Object[] columns) {
this.id = (columns[0] != null)?((BigDecimal)columns[0]).intValue():0;
this.name = (String) columns[1];
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
}
here UserObject constructor will get a Object Array and set data with object.
public UserObject(Object[] columns) {
this.id = (columns[0] != null)?((BigDecimal)columns[0]).intValue():0;
this.name = (String) columns[1];
}
Your query executing function is like bellow :
public UserObject getUserByRoll(EntityManager entityManager,String rollNo) {
String queryStr = "select id,name from users where rollNo = ?1";
try {
Query query = entityManager.createNativeQuery(queryStr);
query.setParameter(1, rollNo);
return new UserObject((Object[]) query.getSingleResult());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
Here you have to import bellow packages:
import javax.persistence.Query;
import javax.persistence.EntityManager;
Now your main class, you have to call this function.
First you have to get EntityManager and call this getUserByRoll(EntityManager entityManager,String rollNo) function. Calling procedure is given bellow:
#PersistenceContext
private EntityManager entityManager;
UserObject userObject = getUserByRoll(entityManager,"1001");
Now you have data in this userObject.
Here is Imports
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
Note:
query.getSingleResult() return a array. You have to maintain the column position and data type.
select id,name from users where rollNo = ?1
query return a array and it's [0] --> id and [1] -> name.
For more info, visit this Answer
Thanks :)
JPA was designed to provide an automatic mapping between Objects and a relational database. Since Integer is not a persistant entity, why do you need to use JPA ? A simple JDBC request will work fine.

Categories

Resources