JPA2 Критерии API.as(String.class) литье в char (1) - Как мне обойти это?
Используя критерии api, у меня есть запрос, который делает что-то вроде:
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();
Полученный SQL-запрос приведет к следующему:
select ...snip aliases... from SourcePath where cast(x'00010002', char(1)) = path;
(путь будет каким-то неприятным старым псевдонимом, но это не имеет значения).
Этот запрос неверен. В частности, cast: cast(x'00010002', char(1))
не является отличным как строка, как указано .as(String.class)
, вместо этого он должен быть либо cast(x'00010002', char)
, либо cast(x'00010002', char(N)
, где N
является достаточно большим числом.
Я выделил причину этого отказа бросания для MySqlDialect, предоставленного org.hibernate. В частности:
public String getCastTypeName(int code) {
if ( code==Types.INTEGER ) {
return "signed";
}
else if ( code==Types.VARCHAR ) {
return "char";
}
...snip...
}
Что дальше по цепочке интерпретируется как char
, которая зарегистрирована в диалоговом окне: registerColumnType( Types.CHAR, "char(1)" );
.
Наконец, на мой вопрос. Как я могу обойти это поведение? Я сообщаю об этом как об ошибке в Hibernate? Расширить ли диалоговое окно и исправить возвращаемый тип из getCastTypeName? Есть ли альтернатива .as
, которая будет соответствующим образом отбрасываться? Или я должен использовать строки везде, где я сейчас использую шестнадцатеричные значения, чтобы избежать касания крайних случаев реализации спящего режима?
Спасибо
СПР
Ответы
Ответ 1
IMHO, вы должны использовать строковый литерал, например cb.literal("\u0001\u0002")
. Причины:
- Это то же самое, что и
cb.literal(0x00010002).as(String.class)
, но менее подробное.
- Не попадает ни в один "крайний случай"
- Это яснее: обрабатывается ли "0x00010002" в Big Endian или LE? Какую кодировку следует использовать?
- Вы можете улучшить удобочитаемость с помощью констант (например:
cb.literal(ASCII_SOH + ASCII_STX)
где SOH = "\ u0001" и STX = "\ u0002" ).
EDIT: добавление лучшего описания, поскольку я не видел "Или, должен ли я использовать строки везде, где я сейчас использую шестнадцатеричные значения"