Hibernate 本机查询 - char(3) 列

Posted

技术标签:

【中文标题】Hibernate 本机查询 - char(3) 列【英文标题】:Hibernate native query - char(3) column 【发布时间】:2011-06-19 21:08:53 【问题描述】:

我在 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=Ecur=U 而不是 cur=EURcur=USD

o[0] 是一个 java.lang.Character

如何获得EURUSD 的完整值?

【问题讨论】:

【参考方案1】:

看起来 Hibernate 将 CHAR(n) 类型的值读取为 Character。尝试将其转换为VARCHAR(n)

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

当通过Session 接口使用Hibernate 时,您可以改为使用addScalar() 显式设置结果类型(在JPA 2.0 中也可以通过unwrap() 访问):

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

从HHH-2220开始,Hibernate JIRA中有很多与此问题相关的未解决问题。

这是来自 HHH-2220 的 cmets 的 Max Rydahl Andersen 的解释:

目前,Hibernate 支持一种从 SQL 类型到 Hibernate/Java 类型的“自动”映射 - 由于在进行此类映射时存在许多模糊性,它有时会与您实际想要的不匹配。

这就是为什么我们总是建议使用显式 addScalar 或者如果您不希望在整个代码中使用 Dialect 的子类来指示您想要多个可能的映射中的哪一个。

CHAR 的问题是最成问题的问题,但它不容易解决——我们需要一个 registerType(type, from, to, typename) 来映射一个范围而不是一个特定的长度......但即便如此您可能会遇到映射歧义(例如,有时您需要一个数组,其他时间是字符串等)。因此,对于任何本机 sql 查询,建议使用 .addScalar - 取决于自动发现总是有风险的,并且应该只使用到最低限度。

如果您在 Hibernate 映射配置文件中描述了您的本机查询,那么您需要为每个返回的值定义 &lt;return-scalar ...&gt;。注意:您必须枚举所有返回值,因为当您显式定义返回类型时,自动发现将被关闭,并且仅返回声明的列。

<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>

【讨论】:

是的,就是这样。找到了此功能的相应 jira 问题。 opensource.atlassian.com/projects/hibernate/browse/HHH-2304 我有一列是 char(10)。当我尝试强制转换(..as VARCHAR)时出现错误。当我使用 cast(.... as CHAR) 时它工作正常 我有一个 CHAR(1) 列,当使用 hibernate 和简单的 createQuery 时,它可以通过 hibernate 正确处理为字符串,但是当我使用 createNativeQuery 时,因此跳过休眠引擎,我必须采用你的查询中的建议:选择 cast(my_flag as VARCHAR2(1))。它有效 难以置信。我正在使用 Hibernate 3.2 并在尝试选择“文字”时遇到了这个问题:select 'Hello' from dual (Oracle) 得到了简单的“H”,真是个笑话!在我的案例中,唯一的解决方案是应用 .addScalar,没有一个 CAST 选项对我有用。

以上是关于Hibernate 本机查询 - char(3) 列的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate:本机 SQL 查询重复列结果

JPA/Hibernate 本机查询无法识别参数

为啥在本机查询 Hibernate 延迟加载的子实体中?

Hibernate:使用@SqlResultSetMapping 映射本机查询的结果集

Hibernate 本机查询:无效的列名错误 SQL-17006

hibernate + spring数据中的本机插入查询