Hi im trying to get number of rows from table using Hibernate based on start and end Date but im Getting not a Valid Month error
Session session = sessionFactory.getCurrentSession();
startDate = "13-02-02 00:00:00";
endDate = "17-02-02 00:00:00";
try{
String hql = "select Count(*) from mytable where PERIOD_START_DATETIME between '"
+ startDate + "' AND '" + endDate + "'";
Query query = session.createQuery(hql);
long count=(long) query.uniqueResult();
return count;
} finally{
session.close();
}
This is my table description
Name NULL TYPE
NAME NOT NULL VARCHAR2(255 CHAR)
PERIOD_END_DATETIME NOT NULL TIMESTAMP(6)
PERIOD_START_DATETIME NOT NULL TIMESTAMP(6)
PROD_OFFER_TERM_TYPE_ID NOT NULL NUMBER(19)
Using string concatenation for generating SQL queries is usually a bad idea because
it's bad for performance (causes re-parsing of the SQL statement for every execution)
it's prone to SQL injection attacks
HQL supports bind variables / prepared statements, so this should work:
String hql = "select Count(*) from mytable where PERIOD_START_DATETIME between :startdate AND :enddate ";
Query query = session.createQuery(hql);
query.setParameter("startdate", startDate);
query.setParameter("enddate", endDate);
(where startDate and endDate are actual java.sql.Timestamp values, not strings).
As the start/end times are SQL TIMESTAMPs in the DB, you can pass in a Timestamp object into the query as follows:
Session session = sessionFactory.getCurrentSession();
final DateFormat df = new SimpleDateFormat("yy-MM-dd");
// omitting the time part will set the time to midnight (00:00:00)
Timestamp start = new Timestamp(df.parse("13-02-02").getTime());
Timestamp end = new Timestamp(df.parse("17-02-02").getTime());
try {
String hql =
"select Count(*) from mytable where PERIOD_START_DATETIME between ? AND ?";
Query query = session.createQuery(hql)
.setTimestamp(0, start)
.setTimestamp(1, end);
long count = (long) query.uniqueResult();
return count;
} finally {
session.close();
}
Make sure you actually pass date values in your query.
You can use the to_date function where you specify the format of the date, as it is represented in the string.
select Count(*)
from mytable
where PERIOD_START_DATETIME between to_date(startDate,'DD-MM-YYYY HH24:MI:SS') AND to_date(endDate,'DD-MM-YYYY HH24:MI:SS');
select Count(*)
from mytable
where PERIOD_START_DATETIME between TO_TIMESTAMP(:startDate, 'YY-MM-DD HH24:MI:SS') AND TO_TIMESTAMP(:endDate, 'YY-MM-DD HH24:MI:SS')
Related
I have Spring JPA.
I have a query like this in sql oracle:
SELECT * FROM MY_TABLE WHERE SYSDATE > MY_DATE + INTERVAL '10' DAY;
I have a CrudRepository in which I use the above query in native mode, like this:
#Query(nativeQuery = true,
value = "SELECT * FROM MY_TABLE WHERE SYSDATE > MY_DATE + INTERVAL :myValue DAY")
public List<Object[]> myMethod(#Param("myValue") String myValue );
I get ORA-00933:
Passing myValue as integer between quotes I get ORA-01867
Passing myValue as integer without quotes I get ORA-00933
How to do it?
See comments on question, there is a similar question/answer for spring/jpa/postgresql, solution for me is:
#Query(nativeQuery = true,
value = "SELECT * FROM MY_TABLE WHERE SYSDATE > MY_DATE + :myValue * (INTERVAL 1 DAY"))
public List<Object[]> myMethod(#Param("myValue") int myValue );
The Query on executing in PostgreSQL Database is fetching the records properly. But, when implemented using createnativeQuery, I am getting Error
ERROR SqlExceptionHelper:131 - ERROR: syntax error at or near ":"
Query Executed successfully in Postgres Database is mentioned below
select d.dt::date as date_current,
coalesce(underwriter_daily_cap, daily_file_cap) as file_cap,
user_id
from generate_series(date '2019-04-05', date '2019-04-09', interval '1'
day) as d(dt)
left join (
select upd.*, ud.daily_file_cap
from mod_underwriter_daily_file_count upd
join lsa_assignment_details ud on ud.user_id = upd.user_id
where ud.user_id = 350
) upd on upd.date_current = d.dt::date
ORDER BY d.dt DESC;
DAO Layer code is as follows
#SuppressWarnings("unchecked")
public List<Object[]> getUnderWriterCap(String dynamicUserId) {
log.info("Entered UserSkillMappingHibDAO :
getUnderWriterCap");
Session session = sessionFactory.getCurrentSession();
Date currentDateMinusFive =
DateUtil.getLastFiveDayOldPSTDate();
Date currentDate = DateUtil.getCurrentPSTDate();
String queryString = " select d.dt::date as date_current,
coalesce(underwriter_daily_cap, daily_file_cap) as file_cap, user_id "
+" from generate_series ( date '"+DateUtil.getDateFormat(currentDateMinusFive)+"', date '"+DateUtil.getDateFormat(currentDate)+"', INTERVAL '1' DAY ) as d(dt) "
+" left join ( select upd.*, ud.daily_file_cap from mod_underwriter_daily_file_count upd "
+" join lsa_assignment_details ud on ud.user_id = upd.user_id where ud.user_id = "+ dynamicUserId
+") upd on upd.date_current = d.dt::date ORDER BY d.dt DESC " ;
List<Object[]> records = session.createNativeQuery(queryString)
.getResultList();
return records;
}
The Exception got in console while executing the above code is as below
Hibernate: select d.dt:date as date_current, coalesce(underwriter_daily_cap, daily_file_cap) as file_cap, user_id from generate_series ( date '2019-04-04', date '2019-04-09', INTERVAL '1' DAY ) as d(dt) left join ( select upd.*, ud.daily_file_cap from mod_underwriter_daily_file_count upd join lsa_assignment_details ud on ud.user_id = upd.user_id where ud.user_id = 403) upd on upd.date_current = d.dt:date ORDER BY d.dt DESC
2019-04-09 18:58 ERROR SqlExceptionHelper:131 - ERROR: syntax error at or near ":"
Position: 14
There are several errors in this. More important than the syntax error is how you're appending a parameter as a string literal.
Instead of:
session.createNativeQuery("select * from tbl where param = '" + value + "'");
You have to use prepared statements (that is the term to look-up). This is extremely important for security.
Query q = session.createNativeQuery("select * from tbl where param = :par1");
q.setParameter("par1", value);
Now as for the syntax error, it's caused by your use of PostgreSQL's custom typecast syntax. You have to replace it with the standard SQL typecast from d.dt::date to cast(d.dt as date), because Hibernate expects : to be the start of a named parameter.
String queryString = "select cast(d.dt as date) as date_current, "
+" coalesce(underwriter_daily_cap, daily_file_cap) as file_cap, user_id "
+" from generate_series ( current_date - 5, current_date, INTERVAL '1' DAY ) as d(dt) "
+" left join ( select upd.*, ud.daily_file_cap from mod_underwriter_daily_file_count upd "
+" join lsa_assignment_details ud on ud.user_id = upd.user_id where ud.user_id = :dynuid ) upd on upd.date_current = cast(d.dt as date) ORDER BY d.dt DESC " ;
List<Object[]> records = session.createNativeQuery(queryString)
.setParameter("dynuid", dynamicUserId)
.getResultList();
I also replaced you current date java calculations with database functions. Instead of doing:
Date currentDateMinusFive = DateUtil.getLastFiveDayOldPSTDate();
Date currentDate = DateUtil.getCurrentPSTDate();
...
.setParameter("ds", DateUtil.getDateFormat(currentDateMinusFive))
.setParameter("de", DateUtil.getDateFormat(currentDate))
You have the database do it for you using current_date - 5 and current_date.
Another thing you should watch-out for, since your DateUtil is using the old java.util.Date class and related stuff is that if you are using a SimpleDateFormatter to format it, then it must be a new instance on every call. Do not optimize it to a static final, because it's not thread-safe. I've suffered from this.
edit: I also believe your query can be optimized much further into this, and it will have the same results:
select upd.date_current, underwriter_daily_cap, daily_file_cap from mod_underwriter_daily_file_count upd
join lsa_assignment_details ud on ud.user_id = upd.user_id
where ud.user_id = :dynuid and
upd.date_current between current_date - 5 and current_date
ORDER BY d.dt DESC
Notice I removed some fields from the select, like user_id, because you are already telling the database which one you want. The one major difference is this query will skip results for days with no entries.
I'm trying to use hiberate query for quite alot of SQL, is there a way to rewrite this sql to make it cleaner. I'm also getting variable is never used for'Query paymentdate'
public void addPrevious(TodaysDate Date){
String paymentDate = ("SELECT PAYMENTDATE FROM table1 where DATE = (SELECT ID FROM _DATE WHERE ID = ( SELECT MAX(ID) FROM _DATE WHERE ID < ( SELECT MAX(ID) FROM _DATE ) ))");
String reportingUnit = ("SELECT REPORTING_UNIT FROM table1 where DATE = (SELECT ID FROM _DATE WHERE ID = ( SELECT MAX(ID) FROM _DATE WHERE ID < ( SELECT MAX(ID) FROM _DATE ) ))");
String insertLastDate = ("INSERT INTO table1(PAYMENTDATE, REPORTING_UNIT, Date) VALUES ("+id+" ,"+paymentDate+", "+amount+", "+asOfDate+")");
Query paymentdate = getSession().createQuery(paymentDate);
Query report = getSession().createQuery(reportingunit);
}
I'm trying to retrieve results from a Oracle 11.2.0.3 database like in the example given at http://docs.oracle.com/javase/tutorial/jdbc/basics/retrieving.html
String query = createQuery(); // SQL query to be used
System.out.println(query);
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
System.out.println("output of first 10 results");
while(rs.next()){
if (i < 10){
String val1= rs.getString(1);
String val2 = rs.getString(8);
String val3 = rs.getString(13);
System.out.println("val1: " + val1 +
", val2: " + val2 + ", val3: " + val3);
}
i++;
}
However, some of the rows returned are different from when I run the same query in SQLDeveloper connected to the same DB schema.
Actually, some of the rows returned in the ResultSet do not match my query.
I am logging into the DB with the same user for both. The java application is using the ojdbc.jar provided at http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html for the Oracle Database 11g Release 2 (11.2.0.3) JDBC Drivers
What could cause such a scenario to happen? There are no changes being made to the tables involved.
The sanitized query:
SELECT DISTINCT T1.COL1, T1.COL2, T1.COL3, T1.COL4, T1.COL5, T1.COL6, T1.COL7, T1.COL8, T1.COL9, COL10, T1.COL11, T1.COL12, T1.COL13
FROM VIEW1 T1, VIEW2 T2
WHERE T1.COL1 = T2.COL1
AND ( (NLSSORT(T1.COL8, 'NLS_SORT=BINARY_AI')=NLSSORT(TO_DATE('2014-05-12 15:25:02', 'YYYY-MM-DD HH24:MI:SS'), 'NLS_SORT=BINARY_AI')
AND T1.COL13<'Example')
OR (NLSSORT(T1.COL8, 'NLS_SORT=BINARY_AI')<NLSSORT(TO_DATE('2014-05-12 15:25:02', 'YYYY-MM-DD HH24:MI:SS'), 'NLS_SORT=BINARY_AI')) )
AND ( T2.ANOTHERCOL = 'SOMEVALUE' AND T1.COL1 = T2.COL)
ORDER BY NLSSORT(COL8, 'NLS_SORT=BINARY_AI') DESC, COL8 DESC, T1.COL13 DESC
In the output, I get:
val1: anid, val2: 2014-05-12 15:29:39, val3: doesnotmatter
As far as I'm aware, that row should not be returned since 2014-05-12 15:29:39 is not less than 2014-05-12 15:25:02. And indeed that row is not found when I run the query in SQLDeveloper.
I guess that col8 is of type date, and I think you problem is in
(NLSSORT(T1.COL8, 'NLS_SORT=BINARY_AI')=NLSSORT(TO_DATE('2014-05-12 15:25:02', 'YYYY-MM-DD HH24:MI:SS'), 'NLS_SORT=BINARY_AI')
your actions:
convert '2014...' to date
convert result to string
convert col8 to string using default format for date column
if your SQL Developer and your java client have different default format for date - you will get different result
I would recomend to change that line to
T1.COL8 = TO_DATE('2014-05-12 15:25:02', 'YYYY-MM-DD HH24:MI:SS')
Also, you don't need NLSSORT in WHERE clause, there is no sorting there.
Now I am thinking that I am wrong.. just don't want to delete it all :)
second try...
one date is 31322D6D61792D313400
another one is 31322D6D61792D313400
they are no less that the other
Query to check
select
NLSSORT(TO_DATE('2014-05-12 15:25:02',
'YYYY-MM-DD HH24:MI:SS'), 'NLS_SORT=BINARY_AI'),
NLSSORT(TO_DATE('2014-05-12 15:29:39',
'YYYY-MM-DD HH24:MI:SS'), 'NLS_SORT=BINARY_AI')
from dual
Any differences if instead of function, modify session?:
ALTER SESSION SET NLS_COMP = 'LINGUISTIC';
ALTER SESSION SET NLS_SORT = 'BINARY_AI';
Below is mysql query which is working fine and giving me expected results on mysql console.
select * from omni_main as t where t.date_time BETWEEN STR_TO_DATE(CONCAT('2011', '08', '01'),'%Y%m%d') AND LAST_DAY(STR_TO_DATE(CONCAT('2012', '08','01'), '%Y%m%d')) group by year(date_time),month(date_time)
I need its JPA equivalent query. Below is what I am trying but its returning nothing.
String queryStr = "select * from OmniMainEntity o where o.dateTime BETWEEN STR_TO_DATE(CONCAT('"+fromYear+"', '"+fromMonth+"','01'), '%Y%m%d') AND "
+"LAST_DAY(STR_TO_DATE(CONCAT('"+toYear+"', '"+toMonth+"','01'), '%Y%m%d'))";
Query query = manager.createQuery(queryStr);
System.out.println("Result Size: "+query.getResultList().size());
Here fromYear, fromMonth, toYear, toMonth are method parameters using in creating queryStr.
Please suggest where I may wrong!
Any other way to achieve goal is also welcome!
As you are using JPA Query, it would be better to not use database-specified sql function, such as STR_TO_DATE.
You can have a try by this way.(A Hibernate way, JPA should be similiar):
First, you can parse a java.util.Date object from "fromYear" and "fromMonth" like below:
DateFormat df = new SimpleDateFormat("yyyyMMdd");
Date startDate = df.parse(fromYear + "" + fromMonth + "01");
Date endDate = df.parse(.....);
Then, set them into the JPA query.
String queryStr = "select * from OmniMainEntity o where o.dateTime BETWEEN :startDate AND :endDate)"; // The query now changed to database independent
Query query = manager.createQuery(queryStr);
query.setDate("startDate", startDate);
query.setDate("endDate", endDate);
At last, doing the search:
System.out.println("Result Size: "+query.getResultList().size());
Your query doesn't have a verb in it. You probably want SELECT in there:
SELECT o FROM OmniMainEntity o WHERE...
Also, you should be using parameterized and typed queries, and it's usual to use short names (o instead of omniMainEnt) to make your queries readable.