Due to some of the restrictions of JPQL (no ordering in subqueries, can't check array equality), I'm having to do some workarounds. Namely, I'm concatenating some numbers (and commas) into a string and checking if they're in an array parameter. (I wish to know which item has exactly a particular set of associated entries in a crossreference table. "For each item
, is the set of other_id/value pairs referencing item
equal to this set I'm passing in as a parameter?") However, the number-to-string conversion tends to go a little weird at high decimal places - I think JPQL (or possibly postgres) is converting the numbers into strings slightly differently than Java is. For instance, JPQL vs Java might give me
1.20991849899292 vs
1.2099184989929199
or maybe the other way around, and new BigDecimal(value).toString()
gives me something again slightly different.
How can I get them to agree? Consider that there's string A, returned from a query, and I wish it to match string B, calculated in Java from the same number. One way I thought of was to reduce the precision of the number before storing it, so it just wouldn't run into the issue. This worked, but only once there were only, say, 10 bits of mantissa left, which was more than I wanted to remove. Another way I thought of was to obtain string B by running, like,
entityManager.createQuery("SELECT CAST(:val as text)", String.class)
.setParameter("val", 0.14520927387582)
.getSingleResult();
...but JPQL refuses to do queries that don't have a FROM
clause. I could make a junk table, always containing exactly one row, but that's really hacky.
Is there a way to tell JPQL how to format a number when it turns it into a string (without knowing which underlying database you're using)? Is there a way to get the SELECT CAST
method to work without being more than a little hacky? Any other, better ideas?