hibernate criteria for a time range search on a Date field - java

Im using Oracle 10g,Hibernate 3,springMVC, jqgrid. I have some Date fields in ORACLE which are mapped as follows
#Temporal(TemporalType.DATE)
#Column(name = "DOC_CREATION_DATE", length = 7,insertable=true,updatable=false)
public Date getDocCreationDate() {
return this.docCreationDate;
}
In my grid I filter date using jqueryCalendar and everything is fine. now I have a new request from the client which is to show the time of documentCreation and they also want to be able to filter by a time range. for example:
find all records created between 6:am and 7:pm, find all records created at 6:am.
I have tried already formatting the date field with
#Temporal(TemporalType.TIMESTAMP)
and that's not what they want
Is there any other approach to this problem, any good ideas how to implement this are very welcome.
the thing is I need to use the same mapped field to query in one column of the Jqgrid for the regular date(12/01/2012 using jqueryCalendar)and add another column for the time part of that same mapped field once that is done I need to query (hibernate criteria) the time column for a range of time
something like this mock:
...
criteria.add(Restrictions.ge("docCreationDate.mappedFieldTimePart",6AM ));
thank you for all the help

The column is of type mapped to a Time, and thus you must compare its value with a Time:
Time sixAM = Time.valueOf("06:00:00");
criteria.add(Restrictions.ge("docCreationDate.mappedFieldTimePart", sixAM));
You can also use a regular date:
Date sixAM = new SimpleDateFormat("HH:mm").parse("06:00");
criteria.add(Restrictions.ge("docCreationDate.mappedFieldTimePart", sixAM));

You must change the #Temporal annotation to use either TemporalType.TIMESTAMP or add another field and annotate it with TemporalType.TIME. Hibernate uses the #Temporal annotation to determine if the field is to be treated like a java.sql.Timestamp or a java.util.Date with the time lopped-off (set to midnight, or 00h 00m 00.0s). This allows developers to use java.util.Date everywhere in their application and never have to worry about the Timestamp class (it's banished from most of our codebase).

Related

Hibernate return 0 record when using with #DateTimeFormat annotation

I have problem when trying to display data to UI.
When I use this query in MySQL to get the Datetime date from my table. It does return the records I want
select flight0_.id as id1_0_, flight0_.arrival_city as arrival_2_0_, flight0_.date_of_departure as date_of_3_0_, flight0_.departure_city as departur4_0_, flight0_.estimated_departure_time as estimate5_0_, flight0_.flight_number as flight_n6_0_, flight0_.operating_airlines as operatin7_0_ from flight flight0_ where flight0_.departure_city='AUS' and flight0_.arrival_city='NYC' and flight0_.date_of_departure='02-05-2018'
This is the result:
But when I use Spring to input the same data to the form and submit it, nothing returns. The input I use is the same.
This is the result:
I specified the #DateTimeFormat annotation in my Controller Class, using pattern the same with what displayed in the database, which is "yyyy-MM-dd"
#RequestMapping("findFlights")
public String findFlights(#RequestParam("from") String from, #RequestParam("to") String to,
#RequestParam("departureDate") #DateTimeFormat(pattern = "yyyy-MM-dd") Date departureDate,
ModelMap modelMap) {
List<Flight> flights = repository.findFlights(from, to , departureDate);
modelMap.addAttribute("flights", flights);
return "displayFlights";
}
Here is my Repository class:
public interface FlightRepository extends JpaRepository<Flight, Long> {
#Query("select f from Flight f where f.departureCity=:departureCity and f.arrivalCity=:arrivalCity and f.dateOfDeparture=:dateOfDeparture")
List<Flight> findFlights(#Param("departureCity") String from, #Param("arrivalCity") String to, #Param("dateOfDeparture") Date departureDate);
}
For testing, I tried to remove that annotation and stop querying from that column, it works as expected. So I'm pretty sure that the #DateTimeFormat annotation is not working at all. Or it works but somehow the Hibernate doesn't understand the pattern I defined.
I also tried to input the value displayed in the screen, which is 2018-02-05 08:00:00.0 but no lucks.
Can someone give me any ideas on this? Please help!
Thanks,
I figured it out myself.
I'm currently working in KL, Malaysia. So the default 'UTC' timezone is not match with MySQL Datetime format. (which still using SYSTEM time).
I made the change in application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/reservation?useLegacyDatetimeCode=false&serverTimezone=Asia/Kuala_Lumpur
And everything works fine now.
You write flight0_.date_of_departure='02-05-2018' in your MySQL query. But 2018-02-05 in your input form and pattern = "yyyy-MM-dd" in your Controller method. If this method gets 2018-02-05 then it "think" that 02 is a month.
I think that problem in the date format yyyy-MM-dd and yyyy-dd-MM. Besides we are talking about American Airlines :)
1 - Try to see the value of dates in debugger.
2 - Try unambiguous dates such as 2017-12-20 and maybe you will see an exception.
3 - Try f.dateOfDeparture>=:dateOfDeparture in your query (maybe problem in time, not in date).

Java Retrieve date records in correct format from mysql

I have a table which was populated by a excel. The date in the columns shows according to my system's timezone when a select query is run in mysql.
But when i run the same query in java using jdbc connection, i am not getting the correct values as which was present in the excel.
I know it is a issue with the timezone. Please guide me with the changes that need to be done for the select query
Result of the following queries are NULL.
SELECT * FROM mysql.time_zone;
SELECT * FROM mysql.time_zone_name;
Just to elaborate on the issue, when i run a select query on date in mysql server, i get the right date values for a column. But when i run the same through a java program, i get converted values to a different timezone.
THe java code is as follows:-
resultList=(List<FosProd>)getEntityManager().createNativeQuery("select fe, count(ldcfe) as Ttlv, count(IF(ldcfe='PTP',1,NULL)) as PTP,DAY(ludfe) as dayte from (select FOS_NAME as fe,Last_Disposition_Code_FOS as ldcfe,Last_Updated_Date_FOS as ludfe from kic.master_mis group by ALLOCATION_DATE,ALLOCATION_BUCKET,BILLED_ID,CUSTOMER_NAME,TOTAL_OUTSTANDING) as s1 where monthname(ludfe)=\"NOVEMBER\" GROUP BY MONTH(ludfe), DAY(ludfe),fe;", FosProd.class).getResultList();
DAY function in SELECT is providing me converted values.
Please help.
public class FosProd implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Size(max = 50)
#Column(name = "fe")
private String fe;
#Basic(optional = false)
#NotNull
#Column(name = "Ttlv")
private long ttlv;
#Basic(optional = false)
#NotNull
#Column(name = "PTP")
#Id
private long ptp;
#Column(name = "dayte")
private Integer dayte;
Likely, it's the JDBC driver "helping" you out, altering the DATETIME/TIMESTAMP values because it's making adjustments to those values because of a difference in the timezone setting of the MySQL server and the JVM.
To see the timezone in effect for your connection to the MySQL server:
SELECT ##time_zone
Compare that to the timezone used by the JVM. If those are the same, then the JDBC driver shouldn't be making any adjustments to the values. If those are different, then it's likely that the JDBC driver is making timezone adjustments to the values.
Change JDBC Connection settings
We had to configure some options on the JDBC connection (MySQL J/Connector) url to stop the JDBC driver from doing brain dead timezone conversions, I think the most important change we made was:
useLegacyDatetimeCode=false
I think we also had to set noTimezoneConversionForDateType=true so timezone adjustments were't made on pure DATE datatypes.
I believe we also did some experimentation with custom mappings, between SQL datatypes and JDBC datatypes. But I don't think those ended up as part of our solution.)
(And obviously, this won't apply if you are using the MariaDB JDBC driver; we're just guessing that you're using MySQL J/Connector.)
NOTE: I'm not saying this is a solution to the issue being reported. The problem description provided in the question is very vague. There's no possible way for anyone to recommend a "solution" based on the information in the question.
Other approaches
That's not the only approach to addressing the issue, there are several other avenuesl suitability of these approaches really depends on your requirements, and what you are trying to achieve.
One "easy" button (probably not the most appropriate solution for you) would be to modify the timezone of the JVM to match the timezone of the MySQL server. BUT... that's going to impact a whole boatload more than just timezone adjustments made by JDBC Driver.
Another "patch" would be to not return DATETIME or TIMESTAMP expressions in the SELECT, but return expressions that have a character datatype instead. That will make the JDBC driver "bypass" any timezone adjustments is doing on DATETIME, (BUT... you'll be returning values that will be mapped into String, not Date or Calendar objects. e.g.
SELECT DATE_FORMAT(mydatecol,'%Y-%m-%d %h:%i:%s') AS mydate_string
FROM
In a similar vein, you could return the UNIX_TIMESTAMP(mydatecol), and that's going to return an integer (number of seconds since midnight Jan 1, 1970 UTC). The value return by that is going to be informed by the setting of the time_zone variable in the MySQL session.)
Again, that's likely not the most appropriate solution.
We assume that you are seeing the "correct" DATETIME values when you run a query against the MySQL server. What's most important here is knowing the setting of the time_zone variable in your MySQL session.
SELECT ##time_zone

Setting Date and Time into Oracle Date field using ebean

Good old date/time problem which I can't to solve with good style...
DB: Oracle 11g
Table contains field: upd_date with Oracle type DATE - I can't change it to TIMESTAMP
My Ebean model:
#Column(name="UPD_DT")
public Timestamp uploadedAt;
I'm trying to save model with current timestamp and then check which value has been saved:
model.uploadedAt = new Timestamp(System.currentTimeMillis());
model.save();
System.out.println("Time before save:" + model.uploadedAt);
System.out.println("Time after save:" + Models.byId(model.id).uploadedAt;
And getting following results:
Time before save:1391633542210
Time after save:1391633542000
I'm know that the difference in these fields because of Oracle DATE doesn't have milliseconds part, but if I will try to update this model object without changing uploadedAt field - I will get: javax.persistence.OptimisticLockException: Data has changed.
Is there any correct way to declare fields in JPA models for Oracle Date field with date and time included, when I don't need to change TimeSpamp every time when I want to update object?
P.S. : Creation like new Timestamp((System.currentTimeMillis()/1000)*1000); looks ugly and all others solution with cutting milliseconds in TimeStamp are very heavy.
I'm trying to find short and clear solution when I don't need to think about superfluous milliseconds.

Java play framework 2.0.4 ebean query

I am wondering how to query the database using the model in play 2.0 with a query like the one I listed below. I didn't see an option to pass in direct sql into the play framework 2.0.
I am trying to get a list of the expenses from a particular month.
SELECT * FROM Expensesdb.expense
WHERE month(expense.purchase_date) = 01
The option I see is to query for all the expenses and then parse each one for the month they are listed using the Date object.
I think there should be an efficient way, I can't seem to find a way to do this using ebean with Java play framework 2.0 to perform this query.
Update
Thanks Nico, I tried the exact code you have, with DateTime and I tried to use the code below, it doesn't return any Expenses. Am I doing something wrong?
Calendar calendar = Calendar.getInstance();
calendar.set(2012, 0, 01);
Date startDate = calendar.getTime();
calendar.set(2012, 0, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
Date endDate = calendar.getTime();
List<Expense> expenses = find.where().between("purchaseDate", startDate, endDate).findList();
return expenses;
I see two options:
1 - Using Ebean mapping
The idea is to search the expenses between the beginning and the end of the month, something like:
Datetime firstDayOfMonth= new Datetime().withDayOfMonth(1);
Datetime lastDayOfMonth = new Datetime().dayOfMonth().withMaximumValue();
return finder.where()
.between("purchaseDate", firstDayOfMonth, lastDayOfMonth).findList();
2 - Using RawSQL
For this, please take a look at the Ebean documentation.
The main drawback of raw sql is that this code will not be portable for different SQL servers (if you don't plan to use several db engine, it will not matter).
+1 for #nico_ekito
On the other hand, while you are suggesting getting all rows from DB and then parsing them in the loop, I'd rather suggest to parse them... while creating and store in format easier to search and index. Just create additional column(s) in your DB, and override save() and/or update(Object o) methods in your model, to make sure, that every change will set the field, ie use String purchasePeriod for storing string like 2012-11;
you can find then:
# in November of ANY year
SELECT * FROM table WHERE purchase_period LIKE '%-11';
# in whole 2012
SELECT * FROM table WHERE purchase_period LIKE '2012-%';
# in December 2012
SELECT * FROM table WHERE purchase_period LIKE '2012-12';
alternatively you can divide it into two Integer fields: purchaseYear, purchaseMonth.
For the first scenario the overriden save() method in the Expense model can look ie like this:
public void save() {
this.purchaseDate = new Date();
this.purchasePeriod = new SimpleDateFormat("yyyy-MM").format(this.purchaseDate);
super.save();
}

lotus notes search by date with Java api

I'm trying to select records by date from a Lotus Notes database and have run into trouble with correctly formatting the date.
Here's the relevant code:
public void runNotes() {
Session s;
try {
s = NotesFactory.createSession((String)null, (String)null, "mypassword");
Database hkDB =
s.getDatabase("NBHDH001/YNM", "H\\DHH00001.nsf", false);
DocumentCollection docs = hkDB.search("[Date]>[2012/03/20]");
Date is a field in the record, and when I looked up records (with FTSearch), the date came back in the format above: [yyyy/mm/dd].
The parameter of the search is what I need here.
i.e. what should I put instead of "[Date]>[2012/03/20]"
I tried various constructions with Calendar and DateFormat, but it's not coming together...
Any suggestions?
You should get rid of the square brackets on the field name. The search method expects a Notes Formula, like what you'd put into a view selection formula:
"Date > [03/20/2012]"
It might also be required that dates are in mm/dd/yyyy format, though if you are in a non-US locale I'm not 100% sure.
You mentioned that you have been doing full text searches in the database, so it is definitely worth mentioning this... If the database actually has a full text index, then you may want to consider using the NotesDatabase.FTSearch() method instead of NotesDatabase.Search(). The FTSearch method will be considerably faster for a large database.
The syntax for FTSearch is different from the syntax for Search. You could use either "FIELD Date > 03/20/2012" or "[Date] > 03/20/2012".

Categories