Updating this
thread again, only for informative purpose...
Michael was right and it's unlikely that the JDBC implementation change the default behaviour. I've been checking different documentation and all this indicate something similar. The point 6.1.5 of the JDBC guide clarifies that the method setObject (<position>, null) won't accept null unless you specify thetype with the corresponding 3rd argument:
http://docs.oracle.com/javase/6/docs/technotes/guides/jdbc/getstart/preparedstatement.html#1003559 .
So, internally, the JPA implementations need to use either the method setObject (<position>, null, <type>) or setNull (<type>) . But I guess that none of these methods is useful for the JPQL queries, because at compile time they do not know what type of parameters are supposed to receive, and because the Query.setParameter method does not allow to specifiy the data type for nulls.
Moreover, I believe that even if the developers of the PostgreSQL JDBC driver implemented the method form setObject (<position>, null), it might fail on the server side. Because some times PostgreSQL is not able to infer the type from the context:
http://www.postgresql.org/docs/9.2/interactive/sql-prepare.html . This point and the fact that PostgreSQL does not contain the implict casts that it got in the past, are a big barrier. In this respect, the first link posted by Michael clarifies it much better than me.
I may be wrong, but believe that JPA would need a way to set the type of query parameters explicitly when they may be null. Either in JPQL (with some kind of operator) or implenting a method like Query.setNullParameter (<type>).
Possible workaround?
Using the non-JPQL function CAST provided by Hibernate and EclipseLink is easier. But it depends on support from the database, so I've thought about a possible universal workaround... I may be wrong, but what if we did something like this?
In the code side, we would check if every parameter is null. If it's, we would set its respective :xxxIsNull parameter to true, and the parameter itself to an arbitrary value which is not null. Because the condition ":xxxIsNull IS TRUE" would be evaluated first (or at least, it would be the cheapest comparison for the database query planner), the arbitrary value would be discarded and would not affect the performance (in theory).
I'm speaking in conditional because it's late and can't test it just now, he he he :P .