Using the criteria api, I have a query which does something like:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<SourcePath> pathQuery = cb.createQuery(SourcePath.class);
Root<SourcePath> pathRoot = pathQuery.from(SourcePath.class);
pathQuery.where(cb.equal(cb.literal(0x00010002).as(String.class), (pathRoot.get(SourcePath_.path))));
TypedQuery<SourcePath> query = entityManager.createQuery(pathQuery);
query.getResultList();
The resulting sql query results something like:
select ...snip aliases... from SourcePath where cast(x'00010002', char(1)) = path;
(path would be some nasty old alias, but that's irrelevant).
This query is incorrect. Particularly, the cast: cast(x'00010002', char(1))
is not a cast to as string, as specified by .as(String.class)
, instead it should be either cast(x'00010002', char)
, or cast(x'00010002', char(N)
where N
is a suitably big enough number.
I've isolated the cause of this cast failure to the MySqlDialect provided by org.hibernate. Particularly:
public String getCastTypeName(int code) {
if ( code==Types.INTEGER ) {
return "signed";
}
else if ( co开发者_StackOverflow中文版de==Types.VARCHAR ) {
return "char";
}
...snip...
}
Which farther down the chain is interpreted as a char
, which is registered by the dialog: registerColumnType( Types.CHAR, "char(1)" );
.
Finally, to my question. How can I work around this behaviour? Do I report it as a bug to Hibernate? Do I extend the Dialog and correct the returned type from getCastTypeName? Is there an alternative to .as
which will appropriately cast? Or, should I use strings everywhere I'm currently using hex-values to avoid touching edge cases of hibernate's implementation?
Thanks idb
IMHO, you should use a String literal like cb.literal("\u0001\u0002")
. Reasons:
- It's the same thing as
cb.literal(0x00010002).as(String.class)
, but less verbose. - Does not hit any "edge case"
- It's clearer: does "0x00010002" be treated in Big Endian or LE? Which encoding should be used?
- You can improve legibility using constants (e.g.:
cb.literal(ASCII_SOH + ASCII_STX)
where SOH="\u0001" and STX="\u0002").
EDIT: Adding a better description, since I didn't see the "Or, should I use strings everywhere I'm currently using hex-values"
精彩评论