Собственный запрос Hibernate - столбец char (3) - PullRequest
16 голосов
/ 02 февраля 2011

У меня есть таблица в Oracle, где столбец SC_CUR_CODE равен CHAR (3)

Когда я делаю:

    Query q2 = em.createNativeQuery("select sc_cur_code, sc_amount from sector_costs");

    q2.setMaxResults(10);

    List<Object[]> rs2 = q2.getResultList();

    for (Object[] o : rs2) {
        System.out.println(">>> cur=" + o[0]);
    }

Я вижу cur=E и cur=U вместо cur=EUR и cur=USD

o[0] - это java.lang.Character

Как я могу получить полное значение EUR и USD?

1 Ответ

36 голосов
/ 02 февраля 2011

Похоже, что Hibernate читает значение типа CHAR(n) как Character. Попробуйте привести его к VARCHAR(n):

Query q2 = em.createNativeQuery(
    "select cast(sc_cur_code as VARCHAR2(3)), sc_amount from sector_costs");  

При использовании Hibernate через интерфейс Session вы можете вместо этого просто установить тип результата с помощью addScalar() (также доступно через unwrap() в JPA 2.0):

Query q2 = em.createNativeQuery(
    "select sc_cur_code, sc_amount from sector_costs");
q2.unwrap(SQLQuery.class).addScalar("sc_cur_code", StringType.INSTANCE);

В Hibernate JIRA есть множество нерешенных проблем, связанных с HHH-2220 .

Вот объяснение Макса Райдала Андерсена из комментариев HHH-2220:

В настоящее время Hibernate поддерживает своего рода «автоматическое» сопоставление типов SQL с типами Hibernate / Java - из-за множества неоднозначностей при выполнении такого сопоставления оно иногда не будет соответствовать тому, что вы на самом деле хотите.

Именно поэтому мы всегда рекомендуем использовать явное addScalar ИЛИ, если вы не хотите, чтобы во всем вашем коде использовалось подклассы Dialect, чтобы указать, какое из множества возможных отображений вы хотите.

Проблема с CHAR является самой проблематичной, но ее нелегко решить - нам понадобится registerType (type, from, to, typename), чтобы отобразить диапазон вместо определенной длины ... но даже тогда вы можете столкнуться с неоднозначностями сопоставления (например, иногда вам нужен массив, другой раз строка и т. д.). Поэтому для любых собственных запросов sql рекомендуется использовать .addScalar - в зависимости от автоматического обнаружения всегда будет рискованно и должно использоваться только до минимума.

Если ваш собственный запрос описан в файле конфигурации отображений Hibernate, то вам нужно определить <return-scalar ...> для каждого возвращаемого значения. Примечание. Необходимо перечислить все возвращаемые значения, так как при явном определении типов возврата автообнаружение отключается и возвращаются только объявленные столбцы.

<sql-query name="myQuery">
    <query-param name="days" type="int" />
    <return-scalar column="count" type="int" />
    <return-scalar column="section_name" type="string" />
    <![CDATA[select count(id) as count, section_name from document where days <= :days]]>
</sql-query>
...