I have a class User with one field called birthDate which is a java.sql.Date.
How do I do a hql query that will retrieve all Users that are between min and max years old?
(My real scenario is slightly more complex than that but that's where I am stuck right now).
UPDATE
It must be an hql expression so I can put the age expression in a computed property.
Calculate the birth dates corresponding to the min and max ages. Then use the below HQL.
Select u from User u where u.birthDate between :minDate and :maxDate
Setup the the minDate and maxDate to the values you computed before executing the query.
It depends on the database. Most have some way of handling date arithmetic. MySQL has a datediff function that will return a number of days so you could divide that by 365 and get pretty close. The MySQL dialect already has datediff as a registered function. For other databases you may need to use different functions and possibly register them in a custom dialect. But you may be off by a little unless you take leap years into account which is tricky in an HQL expression. Using dates is easier because you can keep the month and day constant, change the year, and then use < or > in HQL.
Related
Again, I'm creating this thread to see if someone has the same issues or if someone knows how to improve performance.
Let me explain first the scenario:
I have a JDO entity named for example Product. In that product I have a field of another entity, a simple one (Example Type: long id, String name, String value) and 1 date.
I created 10000 objects of the product but when i try to query the Product with the dates the performance is good but if I add the type.id == 12 then the performance drops from 100ms to 30 secs... if I instead of having a Type object put a long typeId on the Product, then the same query is also fast... What I'm worried is with scalability, should I flatten the structures and work with ids that are not really connected but needs additional application retrieval or is there a way to improve performance on the query on a Product.Type?
Thank you very much in advance.
I've already tried to define fetchGroups, but they don't really work...
What I wanted to do actually is doing a sort of mapping via an ID on the Product, but I couldn't do it with the embedded annotation...
so, let me explain a little better: I have a class named Reading with (one Date timeStamp and a Product p). this is doing a query. If the filter is something like this:
String filter = "timeStamp > fromDate && timeStamp < toDate";
the query executes in 100ms if I do this
String filter = "timeStamp > fromDate && timeStamp < toDate && prod.id == '941'"
for example, it takes 30secs... I've seen the logs, and without the query for the product he only reads from cache, if I add the clause of the Product he seems to fetch all the objects and starts comparing values I imagine...I don't really know what to do, maybe I should disconnect all these classes and start using like a String productID on the Reading class and then everything starts to be fast again... but in reality, the connection is not there, it would be implemented in an application layer... Thanks again... Any advise?
The query generated is something like this:
SELECT FROM core.jdo.model.Readings WHERE timeStamp > fromDate && timeStamp < toDate && EAN.EAN == '002' PARAMETERS java.util.Date fromDate, java.util.Date toDate import java.util.Date
Below is the snapshot of what I have got as a query from sqlite db.
After googling and reading a number of question around, I have come to know that to retrieve maximum datetime using aggregate functions like max() is not possible as sqlite doesn't support much datatypes but treats datatype as text.
So, I have brought this data in a List or at java level. So how could I now get the maximum datetime from this list.
Is there any direct construct for this format in java. Or do we have something at sqlite level that I coudn't find.
texts can be compared, sorted and ordered in SQLite.
Your format appears to be YYYY-MM-dd hh:mm:ss. Lucky for you, ordering this format result in ordering by date.
just
select current_test_id from someTable order by test_datetime desc limit 1
or
select current_test_id, max(test_datetime) from someTable
(or something, not entirely sure for the second one)
if you set the type of datetime field text then you can perform following query
but datetime must be yyyy-mm-dd hh:mm:ss
select max(datetime) from tableName;
A common approach is to store the data converted as long.
Use date.getTime() to get long from your Date instance and Date date = new Date(timestamp); to get a date object from your timestamp.
Once you have a long in your db you can perform any ordering / comparison you want.
To retrive max value from a set of Time of type (String) We have to do some concatenations using sub string .Using this Query max or min Time can be find out using sql lite
select max(datetime(case
when substr(TimeIn,7,2)='PM'
then substr(TimeIn,1,2)+12
else substr(TimeIn,1,2)
end || ':' || substr(TimeIn,4,2) || ':' || '00'))
from tablename
where Date='10/06/2016'
I am using the CriteriaBuilder and CriteriaQuery to build my query to the database, but I have encountered an issue that I do not know how to solve, since I am very new to this whole ordeal called JPA.
In Java, I have a property called timestamp for a class called Report, and it is set to the same corresponding #TemporalType.
I also have a class called Affiliate which has a list of Report objects.
In my query, I want to fetch all the Affiliate objects that do not have a Report in the last Affiliate.maxSilenceMinutes.
My questions:
Are there any ways in standardized JPA to modify dates? Like a CriteriaBuilder.subtractMilliseconds(Expression<Timestamp>, Long) of sorts?
If not, is there a way to cast Expression<Timestamp> to Expression<Long> so that I can subtract on a currentTimestamp literal to get the minimum value for a CriteriaBuilder.lessThanOrEqualTo(greatestReportTimestampMs, minimumAllowedMs)?
I know this might feel like a confusing question, but the main part is simply: Is it possible to go Expression<Timestamp> to Expression<Long>? It throws an exception for me if I try to use the .as(Long.class) method, but which should be the default underlying data type in most DBs anyway?
Hope you guys can help, since I feel kind of stuck :)
If you know the value you want to subtract at the time of querying,
you can subtract beforehand:
Calendar c = new Calendar();
c.setTime(timestamp.getTimestamp());
c.add(DAY, - someNumberOfDays); //or whatever unit you want
Date d = c.getTime();
If not, you probably need to call a database function to do the subtraction, via
CriteriaBuilder.function()
CriteriaBuilder.lessThanOrEqual() works on Comparables. Timestamps are comparable. So you could construct a Timestamp via new Timestamp(long ms)
and compare it with the other expression.
I hope this helps.
This is not built into Hibernate, so you will need a custom function of some kind.
The JDBC standard includes a function escape {fn TIMESTAMPADD( SQL_TSI_SECOND, secs, timestamp)} which should be translated into the correct SQL for the target database, but not all JDBC implementations provide it. There is therefore a chance you can add a custom StandardJDBCEscapeFunction to Hibernate's Dialect to get the result you need.
If you don't have that available, you'll have to find out what the correct database specific implementation is and there is a lot of variability here. For example:
Oracle: (timestamp + secs/86400)
SQLServer: DATEADD(ss,secs,timestamp)
DB2: (timestamp + secs SECONDS)
MySQL: DATE_ADD(timestamp, INTERVAL secs SECONDS)
Once you know it, you can use the correct expression as an SQL criteria.
The fact that date-time manipulation is not standardised in the Dialect and not fully implemented in many JDBCs means that what you are trying to do will be very difficult to write in a database neutral way.
I have a java.util.Date field in an #Entity and would like to get the distinct months from that column.
Suppose I only had three rows, with 14/07/2010, 24/11/1975 and 03/11/1975 (European date format - day/month/year), I would like to get the following back from Hibernate to go into a dropdown for filtering the data:
07/2010
11/1975
(or corresponding Date objects with the other fields set to zero - to be honest precisely how the data comes back isn't too important as I can work around that).
I'm guessing a database-agnostic approach in HQL isn't possible - any suggestions?
What about :
select distinct month(c.birthday), year(d.birthday) from Cat c
I've got an application that uses a hibernate(annotations)/mysql combination for ORM. In that application, I got an entity with a Date field. I'm looking for a way to select on that date within a time range (so hh:mm:ss without the date part).
In MySQL there's a function TIME(expression) that can extract the time part and use that in the where clause, but that does not seem to be available in Hibernate without switching to native queries. Is there an option in hibernate to do this, or should I loop through the results in java and do the comparison there? Would this be much slower as the MySQL solution, since that would not use indexes anyway?
The following functions are available in HQL, maybe you could use them:
second(...), minute(...), hour(...), day(...), month(...), year(...)
Add the expression as a SQL restriction rather than having a full native query. I don't know MySQL specifically, but imagine something like this:
Criteria criteria = session.createCriteria(MyTable.class);
criteria.add(
Expression.sql(
"TIME( {alias}.my_date, 'hh:mm:ss') >= :1",
dateRangeMin,
new StringType()
)
);