Собственный запрос Hibernate - столбец char(3)

У меня есть таблица в 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 ответ

Решение

Похоже, 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 является наиболее проблемной, но ее нелегко решить - нам нужен регистр Type(type, from, to, typename) для отображения диапазона вместо определенной длины... но даже тогда вы можете столкнуться в отображении неоднозначностей (например, когда-нибудь вам понадобится массив, строка других времен и т. д.) Следовательно, использование.addScalar рекомендуется для любых собственных запросов sql - в зависимости от автоматического обнаружения всегда будет рискованно и должно использоваться только до минимума.

Если ваш собственный запрос описан в файле конфигурации отображений 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>
Другие вопросы по тегам