Hibernate native query - char (3) column

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

Вот объяснение Max Rydahl Andersen из комментариев HHH-2220:

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

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

Проблема с CHAR является наиболее проблематичной, но ее нелегко исправить - нам понадобится registerType (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>