i have trouble with select only month or year in JPA
in mysql i write statement follow:
select * from table where Month(date) = 12 ;
and in entity bean i write follow:
select t from table t where Month(t.date) = 12;
but it throw Error !!
PS: sorry i can't attach my stacktrace because i'm not at home :D
sorry but you cant do this with JPA as far as i know. hibernate's hql on the otherside knows stuff like month() hour() and minute().
check this question: JPA Date Arithmetic?
hope that helped
Not part of JPA, and consequently in the role of vendor extensions. Most JPA implementations support it ... and you don't say which one you're using. DataNucleus certainly supports MONTH, YEAR, DAY, HOUR, MINUTE, SECOND.
This might help someone.
Few JPA implementations have built-in support for date/time functions.
EclipseLink
EclipseLink supports EXTRACT allowing any database supported date/time
part value to be extracted from the date/time. The EXTRACT function is
database independent, but requires database support. EXTRACT(YEAR,
model.currencyExchangeDate), but it requires EclipseLink 2.4.x
FUNC allows for a database function to be call from JPQL. It allows calling any database functions not supported directly in JPQL.
To call the DB function MyFunc(a, b, c) use FUNC('MyFunc', a, b, c).
You can try FUNC('YEAR', currencyExchangeDate) to call 'YEAR'
function.
Hibernate
In HQL, you can have date function YEAR(date), MONTH(date), DAY(date)
to extract required details. Other time functions supported are
HOUR(date), MINUTE(date), SECOND(date).
Criteria API
CriteriaBuilder#function() : Create an expression for the execution
of a database function.
CriteriaQuery<IptExchangeratelines> cq = cb.createQuery(IptExchangeratelines.class);
Root<IptExchangeratelines> exRateLine = cq.from(IptExchangeratelines.class);
cq.where(cb.equal(cb.function("year", Integer.class,
exRateLine.get(exRateLine_.currencyExchangeDate)), year)
.and(cb.equal(cb.function("month", Integer.class,
exRateLine.get(exRateLine_.currencyExchangeDate)), month)));
Related
As we have seen that after you get a data source. We need to configure SQL dialects based on the database we use. After we select a particular dialect, How would that be used to make SQL queries specific to DB. Do frameworks like hibernate and JOOQ construct SQL queries in string based on the selected dialect ? If so which would be the most optimal way to support this in a framework of our own ?
Do frameworks like hibernate and JOOQ construct SQL queries in string based on the selected dialect
Yes. In jOOQ, there's an internal StringBuilder that collects SQL fragments from your expression tree, which are generated for your target SQL dialect specifically. You can see how that works in action on this website: https://www.jooq.org/translate. Try translating for example this input: SELECT * FROM t LIMIT 1 (which could correspond to your jOOQ API usage ctx.selectFrom(T).limit(1). It translates to:
-- Oracle 12c and more
SELECT * FROM t FETCH NEXT 1 ROWS ONLY
-- Oracle 11g and less
SELECT *
FROM (
SELECT x.*, rownum rn
FROM (SELECT * FROM t) x
WHERE rownum <= 1
)
WHERE rn > 0
If so which would be the most optimal way to support this in a framework of our own ?
You need:
An expression tree representation of your SQL query.
Optionally, you can parse a string to build this expression tree, like jOOQ's parser if you want to support actual SQL, or you can have your own language abstraction like Hibernate did with HQL / JPQL
Traverse that expression tree using something like a visitor to collect the SQL strings and bind variables.
But!
Do not build your own when you have off the shelf products like jOOQ or to some lesser extent Hibernate that can do the same. Building such a generic SQL abstraction is really difficult, and unless you want to actually sell such a product (you probably don't given your question), investing this time into building this product is not worth it at all.
The above LIMIT emulation is one of the more simple examples from jOOQ. Here's a lot more to help you decide against rolling your own, and that answer is still just scratching the surface of what jOOQ does behind the scenes.
I have been doing queries in EF and everything working great but now i have in the db 2 fields that are actually CHAR.. They hold a date but in the form of a number, in SQL Management Studio i can do date1 >= date2 for example and i can also check to see if a number i have falls in between these 2 dates.
Its nothing unusual, but basically a field that represents a date (the number grows as the date does)...
Now in EF when i try to do >= it states you can't do this on a string, ok understand its c# so i tried doing Convert.ToDecimal(date1) but it gives me an error saying that its not supported.
I have no option of changing the db fields, they are set in stone :-(
the way i got it to work was request of details and do a .ToList and then use the .ToDecimal and it works but of course this is doing it in memory! and this defeats the object of EF i.e. for example adding to the query using iqueryable.
Another way i got it to work was to pass the SQL query to SqlQuery of the dbcontext but again i lose a lot of ef functionality.
Can anyone help?
I am really stuck
As you say that you tried >= I assume that it would work for you if you could do that in plain SQL. And that is possible by doing
String.Compare(date1, date2) >= 0
EF is smart enough to translate that into a >= operator.
The advantage is that you do not need to compare converted values, so indexes can be used in execution plans.
First of all, you can at least enable deferred execution of the query by using AsEnumerable() instead of ToList(). This won't change the fact that the database would need to return all the records when you do in fact execute the query, however.
To let the database perform the filtering, you need your query to be compatible with SQL. Since you can't do ToDecimal() in SQL, you need to work with strings directly by converting your myvar to a string that is in the same format as dateStart and dateEnd, then form your query.
I have an entity Event which has fields startDate and endDate. I'd like to select only those events that have at most x days left to the their endDate. I want to do this in JPQL and with only one query. How can I do this?
JPA does not provide any standard date/time functions. You can use a native SQL query using SQL EXTRACT,
Or, if you are using EclipseLink you can use the FUNC JPQL operator to call a database specific function, or use EXTRACT if using EclipseLink 2.4,
See,
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL#Functions
I'm using Zend Framework for my website and I'd like to retrieve some data from my PostgreSQL database.
I have a request like :
SELECT DISTINCT ON(e.id) e.*, f.*, g.* FROM e, f, g
WHERE e.id = f.id_e AND f.id = g.id_f
This request works well but I don't know how to convert the DISTINCT ON(e.id) with Zend.
It seems that I can get DISTINCT rows but no distinct columns.
$select->distinct()->from("e")->join("f", "e.id = f.id_e")
->join("g", "f.id = g.id_f");
Any idea on how to make a select with distinct column ?
Thanks for help
You probably can't do this with Zend Framework since distinct on is not part of the SQL standard (end of page in Postgres documentation). Although Postgres supports it, I would assume its not part of Zend Framework because you could in theory configure another database connection which does not offer support.
If you know in advance that you're developing for a specific database (Postgres in this case), you could use manually written statements instead. You'll gain more flexibility within the queries and better performance at the cost of no longer being able to switch databases.
You would then instantiate a Zend_Db_Apdapter for Postgres. There a various methods available to get results for SQL queries which are described in the frameworks documentation starting at section Reading Query Results. If you choose to go this route I'd recommend to create an own subclass of the Zend_Db_Adapter_Pgsql class. This is to be able to convert data types and throw exceptions in case of errors instead of returning ambiguous null values and hiding error causes.
Let say you have a class with a java.util.Date field. Maybe a To do class or an Event planner class.
#Temporal(TemporalType.TIMESTAMP)
private Date startTime;
This will map to a datetime column in MySQL.
There are use cases when you want to know precisely when this Event occurs. "What is scheduled for Aug 11, 2011 at 8 PM?"
Sometimes you just want to know which events are planned for a specific date. "What is scheduled for August 11, 2011?"
If your JPAQL is:
SELECT blah blah etc. WHERE ti.startTime = :d1
and the parameter is a java.util.Date instance:
query.setParameter("d1", date, TemporalType.DATE);
your results will be restricted by the date but also the time.
This is such a common use case that I'm surprised that there is no simple way to do this even in JPA 2.0.
I'd rather not use a vendor specific hack nor play around with strings/substrings.
How have you solved this problem?
I know I'm a little late, but I've found a way to do this.
I was using a jpql like this:
select s from S s where date(s.someDate) = :param
And I set the param with:
query.setParameter("param", param, TemporalType.DATE);
The way I've found to do this with Criteria Query was:
builder.equal(
builder.function("date", Date.class, root.get(S_.someDate)),
param
);
At least, with MySql it works.
I hope it can help.
select ... where ti.startTime >= :theDay and ti.startTime < :theNextDay
is a relatively easy solution to implement, and works on any JPA implementation.
Hibernate also allows adding functions to a dialect, in order to generate custom SQL.