HQL to query records between two dates - spring

I am trying to query all customers records using HQL in my Spring/ Hibernate app that have DateAdded between Date1 and Date2 OR LastSeen between Date1 and Date2, so I've build this HQL query in the Repository/ DAO class:
sessionfactory.getCurrentSession().createQuery("from Customer c where c.dateAdded BETWEEN '"+startDate+"' AND '"+endDate+"' OR c.lastSeenDate BETWEEN '"+startDate+"' AND '"+endDate+"'").list();
I've debugged the app to check the startDate and endDate and found that they are sent as:
startDate: Wed Jan 22 01:16:57 HKT 2014
endDate: Wed Jan 29 01:16:57 HKT 2014
In DB, I am 100% sure there is one record at least meeting this query, as this record DateAdded and LastSeen are as follows:
2014-01-23 15:33:38
2014-01-25 15:33:38
So can someone please tell me what I am doing wrong / missing here?

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String frmDate = format.parse(startDate);
String enDate = format.parse(endDate);
sessionfactory.getCurrentSession()
.createQuery("FROM Customer AS c WHERE c.dateAdded BETWEEN :stDate AND :edDate ")
.setParameter("stDate", frmDate)
.setParameter("edDate", enDate)
.list();
hope this will help!

This is an old post, but I figured it might help someone. Setting .setTimeStamp should do the trick.
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String frmDate = format.parse(startDate);
String enDate = format.parse(endDate);
sessionfactory.getCurrentSession()
.createQuery("FROM Customer AS c WHERE c.dateAdded BETWEEN :stDate AND :edDate ")
.setTimestamp("stDate", frmDate)
.setTimestamp("edDate", enDate)
.list();

SimpleDateFormat sf=new SimpleDateFormat("dd-MM-YYYY");
String fromDate=null;
String toDate=null;
fromDate=sf.format(startDate);
toDate=sf.format(endDate);
sessionfactory.getCurrentSession().createQuery("from Customer where dateAdded BETWEEN '"+startDate+"' AND '"+endDate+"'");

SimpleDateFormat formatter = new SimpleDateFormat("MM-dd-yyyy");
Calendar c = Calendar.getInstance();
c.setTime(new Date()); // Now use today date.
c.add(Calendar.DATE, 90);
Date fromDate = null, toDate = null;
String fromDateStr = formatter.format(new Date());
String toDateStr = formatter.format(c.getTime());
try {
fromDate = formatter.parse(fromDateStr);
toDate = formatter.parse(toDateStr);
} catch (ParseException e) {
e.printStackTrace();
}
query.setParameter("stDate", fromDate);
query.setParameter("edDate", toDate);

It's important to know that when using BETWEEN “setDate” will truncate the HQL date value passed as parameter and ignore the hours, minutes, seconds. This is very important to note especially if you have an HQL query checking between dates from different days because using “setDate” will interpret the date interval as between midnight of the specified dates.
The solution is to use “setParameter” instead of “setDate” which causes the HQL date values to be interpreted as dates and times.
here's a few examples in my site for those interested http://www.coding-dude.com/wp/java/hql-date-datetime-quick-tip/

I had similar issue. When we use end date (Wed Jan 29), the system looks for Wed Jan 29 00:00:00, which is just like choosing Jan 28. In order to avoid such case, we can add one day to the end date. This also explains why we do not have issue with the start date.
Surprisingly, this issue does not exist when we use hibernate criteria.

You need to annotate with #JsonFormat the same way the date filters and date field as follows:
Class Filter {
...
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd/MM/yyyy HH:mm", timezone="America/Sao_Paulo")
private Date startDate;
}
Class YourObject {
...
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd/MM/yyyy HH:mm", timezone="America/Sao_Paulo")
private Date DateAdded;
}
The pattern and timezone should be adjusted to your region.

Try something like this:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date fromDate = df.parse(startDate);
Date toDate = df.parse(endDate);
Criteria criteria = sessionfactory.getCurrentSession().createCriteria(Customer.class)
.add(Restrictions.between("dateAdded", fromDate , toDate ));
List<Customer> listCustomer = criteria.list();
Hope this helps..!!

Related

Mockito verify 'arguments are different', while they are identical

I am testing spring RestController. I use several prams to call controller. The call is successful and i got expected response. But Mockito is not able to verify mock call of service. Why?:
...
private static final String TRACE_ID = "1";
private static final String MAPPED_ID = "2";
...
#Test
void getLogMessages() throws Exception {
LogMessageDto dto = easyRandom.nextObject(LogMessageDto.class);
Integer slice = 0;
Integer limit = 60;
Integer serviceLimit = 50;
Date startFrom = new Date();
Date startTo = new Date();
MultiValueMap<String, String > params = new LinkedMultiValueMap<>();
params.put("traceId", Collections.singletonList(TRACE_ID));
params.put("mappedId", Collections.singletonList(MAPPED_ID));
params.put("slice", Collections.singletonList(slice.toString()));
params.put("limit", Collections.singletonList(limit.toString()));
params.put("startFrom", Collections.singletonList(startFrom.toString()));
params.put("startTo", Collections.singletonList(startTo.toString()));
Mockito.when(logMessageService.getLogMessages(anyString(), anyString(), anyInt(), anyInt(), any(Date.class),
any(Date.class)))
.thenReturn(new PageImpl<>(Collections.singletonList(dto)));
mockMvc.perform(get("/feed-logs-service/messages")
.queryParams(params))
.andExpect(status().isOk())
.andExpect(jsonPath("$.content[0].content", equalTo(asParsedJson(dto.getContent()))))
.andExpect(jsonPath("$.content[0].fields", equalTo(asParsedJson(dto.getFields()))));
verify(logMessageService).getLogMessages(eq(TRACE_ID), eq(MAPPED_ID), eq(slice), eq(serviceLimit), eq(startFrom),
eq(startTo));
verifyNoMoreInteractions(logMessageService);
}
the test execution results in:
Argument(s) are different! Wanted:
service.LogMessageService#0 bean.getLogMessages(
"1",
"2",
0,
50,
Sun Feb 06 14:52:13 MSK 2022,
Sun Feb 06 14:52:13 MSK 2022
);
-> at controller.LogMessageControllerTest.getLogMessages(LogMessageControllerTest.java:97)
Actual invocations have different arguments:
service.LogMessageService#0 bean.getLogMessages(
"1",
"2",
0,
50,
Sun Feb 06 14:52:13 MSK 2022,
Sun Feb 06 14:52:13 MSK 2022
);
intellij idea shows additional empty line when i click 'Click to see difference' link, is it the reason?, and how to pass trough? Thanks for any suggestions.
EDIT:
controller method:
#GetMapping("/messages")
public Page<LogMessageDto> getLogMessages(#RequestParam String traceId, #RequestParam String mappedId,
#RequestParam(required = false) Integer slice,
#RequestParam(required = false, defaultValue = SIZE_LIMIT) Integer limit,
#RequestParam(required = false) #DateTimeFormat(pattern = "EEE MMM dd HH:mm:ss ZZZ yyyy") Date startFrom,
#RequestParam(required = false) #DateTimeFormat(pattern = "EEE MMM dd HH:mm:ss ZZZ yyyy") Date startTo) {
limit = checkLimit(limit);
return logMessageService.getLogMessages(traceId, mappedId, slice, limit, startFrom, startTo);
}
From the test:
Date startFrom = new Date();
These values are parsed to a String:
params.put("startFrom", Collections.singletonList(startFrom.toString()));
But when verifying it's not the String representation that's validated:
verify(logMessageService).getLogMessages(..., eq(startFrom), ...);
I could tell you the problem with this. But as an exercise to learn how Date works I suggest you compare the startFrom.getTime() from the variable created in the test, and the call to logMessageService.getLogMessages(...)
Edit to add an explanation of the problem
The Date is represented as a 64 bit integer internally, down to millisecond. That's what's used when the equals-method is called. When the toString method is called it's converted to a human readable format, and by default loses the millisecond bit. When it's converted back to a Date in the controller it's with zeros as the milliseconds. Which is verified against the Date with milliseconds.

Spring Data JPA between date range return null

I am using native Query for the date between operators but it is returning null.
when I run this with static dates
#Query(value ="SELECT a.name,m.title from meetings m ,attendies a where m.id =a.m_aid and (start_time BETWEEN '2021-04-03 11:00:16' AND '2021-04-03 11:30:15' )",nativeQuery = true)
public List<Object[]> findConflictMettinds( Date startTime, Date endTime );
able to get data, but when tried to return with dynamic values it returns null always.
below are the different methods I tried so far
#Query(value ="SELECT a.name,m.title from meetings m ,attendies a where m.id =a.m_aid and (m.start_time BETWEEN ?1 AND ?2 )",nativeQuery = true)
public List<Object[]> findConflictMettinds(#Param("startTime") Date startTime,#Param("endTime") Date endTime ); #Query(value ="SELECT a.name,m.title from meetings m ,attendies a where m.id =a.m_aid and (m.start_time BETWEEN :startTime AND :endTime )",nativeQuery = true)
public List<Object[]> findConflictMettinds(#Param("startTime") Date startTime,#Param("endTime") Date endTime );
#Query(value ="SELECT a.name,m.title from meetings m ,attendies a where m.id =a.m_aid and (m.start_time > :startTime AND m.start_time <:endTime )",nativeQuery = true)
public List<Object[]> findConflictMettinds(#Param("startTime") String startTime,#Param("endTime") String endTime );
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
repository.findConflictMettinds(dateFormatter.format(startTime), dateFormatter.format(endTime))
Also you don't have to use native query but if it is necessary then you can use with given example. You can also look for Search records between two dates using Spring Data JPA native query?
Try to pass string of date as model attribute instead of as param
public List<Object[]> findConflictMettinds(#ModelAttribute("startTime") String startTime,#ModelAttribute("endTime") String endTime );

Can't Convert JavaFX Datepicker date to a specified date format

Cannot convert javaFX Datepicker date to a specific(dd-MM-yyyy) date format.
here i using two Methods using SimpleDateFormat, but i got some errors like these.
when using this method
String testDateString = dpfrom.getValue().toString();
DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
Date d1 = df.parse(testDateString);
System.out.println("Date in dd/MM/yyyy format is: "+df.format(d1));
the error message is:
java.text.ParseException: Unparseable date: "2019-09-23"
while using this method:
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
Date d1= sdf.parse(dpfrom.getValue().toString());
System.out.println(d1);
i got this Output:
Fri Mar 11 00:00:00 IST 29
but i want the output like this:
23-09-2019
please help me to solve this issue.
I hope you guys to solve this problem.Thank you...
Try this
private void dateTest() {
try {
String testDateString = "2019-09-23";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = df.parse(testDateString);
System.out.println(d1);
df = new SimpleDateFormat("dd-MM-yyyy");
String d2 = df.format(d1);
System.out.println(d2);
} catch (ParseException e) {
e.printStackTrace();
}
}
output
Mon Sep 23 00:00:00 ICT 2019
23-09-2019
in your case change testDateString to dpfrom.getValue().toString();
As you have tagged your question as Java8 JavaFX8 question. Here is a more Java-8 fashion answer with LocalDate :
String static final DATE_PATTERN = "yyyy-MM-dd"
String datePickerValue = dpfrom.getValue().toString();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(DATE_PATTERN);
LocalDate date = LocalDate.parse(datePickerValue, dtf);
This is actually the new Java Time API since Java 8 (java.time) package
Trying to convert LocalDate to String and then try to parse it as a Date is a bad idea. Simply use DateTimeFormatter to convert to a string directly:
final String format = "dd-MM-yyyy";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
System.out.println("Date in " + format + " format is: " + formatter.format(d1));

How do I get my hour, minutes, seconds, and milliseconds to be zeros?

I'm trying to get my format to be 2016-07-08T00:00:00.000Z.
String myDate = "20160708";
LocalDate myLocalDate = LocalDate.parse(myDate, DateTimeFormatter.BASIC_ISO_DATE);
OffsetDateTime myOffsetDate = myLocalDate.atTime(OffsetTime.now(ZoneOffset.UTC));
System.out.println(myOffsetDate); //2016-07-08T14:58:23.170Z
Well don't say "I want it to use the current time"! That's what this is doing:
OffsetTime.now(ZoneOffset.UTC)
If you just want an OffsetDateTime from a LocalDate by providing a zero offset and midnight, you can use:
OffsetDateTime myOffsetDate = myLocalDate
.atTime(LocalTime.MIDNIGHT)
.atOffset(ZoneOffset.UTC);
Or if you prefer:
OffsetDateTime myOffsetDate = myLocalDate
.atTime(OffsetTime.of(LocalTime.MIDNIGHT, ZoneOffset.UTC));
(Personally I prefer the first version, myself...)
Note that that's just getting you the right OffsetDateTime. If you want to format that with milliseconds and seconds, you'll need to do that explicitly:
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
System.out.println(myOffsetDate.format(formatter));
As noted in comments, if you're find with a ZonedDateTime instead of an OffsetDateTime, you can use
ZonedDateTime myOffsetDate = myLocalDate.atStartOfDay(ZoneOffset.UTC);
I am not quite sure if you can get the ISO_INSTANCE date format with the given string using LocalDate. but you can use below java 8 piece of code to get the required format.
public String getISO_8601DateFormat(String yyyyMMdd){
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String requiredFormat = null;
try {
Date inputDate = sdf.parse(yyyyMMdd);
long dateLongRepresentation = inputDate.getTime();
long myTimeZoneOffset = TimeZone.getTimeZone(ZoneId.systemDefault()).getOffset(inputDate.getTime());
Instant instance = Instant.ofEpochMilli(dateLongRepresentation + myTimeZoneOffset);
requiredFormat = instance.toString();
} catch (ParseException e) {
e.printStackTrace();
}
return requiredFormat;
}
Enjoy coding with java :)

input date using jdbc to hsqldb

How do i get all the rows having endDate greater than current date? do i have to use setString() or setDate()? they are both not working!!!
What is the correct way to do it?
ResultSet is empty but database contains data for the given sql statement
public ArrayList<AddBean> listPendingTasks() {
java.util.Date date = new java.util.Date();
String modifiedDate= new SimpleDateFormat("yyyy-MM-dd").format(date);
Connection con = JDBCHelper.getConnection();
PreparedStatement ps_sel = null;
ArrayList<AddBean> c = new ArrayList<AddBean>();
ResultSet rs = null;
try {
ps_sel = con.prepareStatement("select * from tasks where enddate > ? order by enddate");
ps_sel.setString(2, modifiedDate);
ps_sel.execute();
rs = ps_sel.getResultSet();
while(rs.next())
{
AddBean ab = new AddBean();
ab.setTname(rs.getString(2));
ab.setCategory(rs.getString(3));
ab.setStartdate(rs.getString(4));
ab.setEnddate(rs.getString(5));
ab.setDescription(rs.getString(6));
ab.setPriority(rs.getString(7));
c.add(ab);
}
return c;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
try this
If your table has a column of type DATE:
Query : SELECT * FROM [values] v WHERE date >= '2013-06-03';
Then use this method java.sql.Date.valueOf(java.lang.String)
ps.setDate(2, java.sql.Date.valueOf("2015-09-13"));
Updated with Date and Time Types:
The DATE type is used for values with a date part but no time part. MySQL retrieves and displays DATE values in 'YYYY-MM-DD' format. The supported range is '1000-01-01' to '9999-12-31'. MySQL retrieves and displays TIME values in 'HH:MM:SS' format. TIME values may range from '-838:59:59' to '838:59:59'.
String QUERY = "UPDATE TABLE_NAME SET dateValue=?, timeValue=?, timeStampText=? WHERE rowIdentify=?";
PreparedStatement pstmt = con.prepareStatement( QUERY );
pstmt.setDate(1, java.sql.Date.valueOf( localDate )); // DATE Type
pstmt.setTime(2, java.sql.Time.valueOf( localTime )); // TIME Type
pstmt.setString(3, localDateTime ); // TEXT Type
pstmt.setString(4, conditionValue );
Sample code to get the above Date fields value. getDateFromEpochTime()
long startTime=System.currentTimeMillis();
String str = getDateFromEpochTime(startTime);
CharSequence charSequence = str.subSequence(0, str.length());
String pattern = "yyyy-MM-dd HH:mm:ss";
DateTimeFormatter dateTimeFormatter = java.time.format.DateTimeFormatter.ofPattern( pattern );
LocalDate localDate = java.time.LocalDate.parse( charSequence, dateTimeFormatter );
LocalTime localTime = java.time.LocalTime.parse( charSequence, dateTimeFormatter );
LocalDateTime localDateTime = LocalDateTime.parse( charSequence, dateTimeFormatter);
Java SQL driver doesnot support java.sql.Timestamp for DATETIME or TIMESTAMP type of Table column. Try to use PreparedStatement when query contains Date and Time Types types.
learn the date format of the db. hsql db supports 'yyyy-mm-dd'. If you are using prepared statements, then you can input date as a String or a date. that is not going to make a difference. I recommend using string. Using date is a little complicated for beginners because its not util date. Its sql date. Date formats can sometime be troublesome.

Resources