`
zl07104
  • 浏览: 7936 次
社区版块
存档分类
最新评论

hibernate下SQLQuery返回BigInteger而不是Long的问题

阅读更多
    使用数据库为mysql5.1.6,hibernate版本为4.3.11.Final。
    遇到问题:在使用hibernate的SQLQuery执行sql查询时,执行count语句或者查询数据库中的bigint(20)类型数据,返回的BigInteger类型,不是Long类型。然而在使用hibernate的Query执行hql查询时,返回的都是Long类型。甚至于使用原生的JDBC方法,获取的结果类型也是Long类型。代码如下:
    User类
@Entity
@Table(name = "user", catalog = "newsclient_hnxxt", uniqueConstraints = @UniqueConstraint(columnNames = {
        "schoolId", "userId" }))
public class User implements java.io.Serializable {
 
    // Fields
 
    private Long userId;
    private String username;
    private String name;
    private String password;
    private String mobile;
    private Integer schoolId;
    private String orderType;
    private String role;
    private Integer status;
    private Timestamp createTime;
    private Timestamp updateTime;
    private Timestamp loginTime;
    private Date expireTime;
     
    private String schoolName;
    
    //省略constructor,省略getter、setter,shoolName是临时属性@Transient
}

    dao层
    count方法:
/**
     * 执行sql count查询
     * @param sql
     * @param values
     * @return
     */
    protected long countSqlResult(final String sql, final Map<String, ?> values) {
        String countSql = prepareCountSql(sql);
        //Hibernate Query执行count,返回结果类型为Long,而SQLQuery执行count返回类型为BigInter????
        Long count = (Long)createSQLQuery(countSql, values).uniqueResult();
        return count;
    }

    findPage方法:
/**
     * 按sql分页查询.
     * 
     * @param page 分页参数.
     * @param sql sql语句.
     * @param values 命名参数,按名称绑定.
     * 
     * @return 分页查询结果, 附带结果列表及所有查询输入参数.
     */
    @SuppressWarnings("unchecked")
    public <X> Page<X> findPage(Class<X> clasz,final Page<X> page, final String sql, final Map<String, ?> values) {
        Assert.notNull(page, "page不能为空");
 
        Query q = createSQLQuery(sql, values);
        if ("Map".equals(clasz.getSimpleName())) {
            q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        } else {
            q.setResultTransformer(Transformers.aliasToBean(clasz));
        }
 
        if (page.isAutoCount()) {
            long totalCount = countSqlResult(sql, values);
            page.setTotalCount(totalCount);
        }
 
        setPageParameterToQuery(q, page);
 
        List result = q.list();
        page.setResult(result);
        return page;
    }

    service层
    测试调用方法:
public Page<User> findPage(Page<User> page) {
        StringBuffer sb = new StringBuffer();
        sb.append("select u.userId, s.name as schoolName ");
        sb.append("from User u, School s ");
        sb.append("where u.schoolId = s.id and u.userId = 13323712806");
        Map<String, Object> params = null;
        return userDao.findPage(User.class, page, sb.toString(), params);
    }

    count报错信息
java.lang.ClassCastException: java.math.BigInteger cannot be cast to java.lang.Long

    findPage报错
IllegalArgumentException occurred while calling setter for property [com.zlstudy.entity.User.userId (expected type = java.lang.Long)]; target = [com.zlstudy.entity.User@4c0a66bc], property value = [13323712806]
Caused by: java.lang.IllegalArgumentException: argument type mismatch

    原因及解决方法:
    1、使用addScalar,为查询列指定返回类型
Query q = createSQLQuery(sql, values).addScalar("userId", StandardBasicTypes.LONG);

    这是网上给出的最普遍的解决方法,这样只能针对某个返回类做特殊处理。但是我的findPage方法是在PagingHibernateDao类,作为通用方法,不想针对某个返回类进行特殊处理,否则就不能够通用。
    2、自定义方言类,修改org.hibernate.dialect.Dialect的构造方法,hibernate使用自定义方言类
    查看hibernate的源代码,hibernate对于未指定的返回类型的查询列,会根据ResultSet.getMetaData().getColumnType(...)的sqlType编号匹配相应的类型,匹配的类型放在放在方言类org.hibernate.dialect.Dialect中。
    hibernate部分源码:
    org.hibernate.loader.Loader.class类
       
   
/**
     * Execute given <tt>PreparedStatement</tt>, advance to the first result and return SQL <tt>ResultSet</tt>.
     */
    protected final ResultSet getResultSet(
            final PreparedStatement st,
            final RowSelection selection,
            final LimitHandler limitHandler,
            final boolean autodiscovertypes,
            final SessionImplementor session)
    throws SQLException, HibernateException {
 
        try {
            ResultSet rs = session.getTransactionCoordinator().getJdbcCoordinator().getResultSetReturn().extract( st );
            rs = wrapResultSetIfEnabled( rs , session );
 
            if ( !limitHandler.supportsLimitOffset() || !LimitHelper.useLimit( limitHandler, selection ) ) {
                advance( rs, selection );
            }
 
            if ( autodiscovertypes ) {
                autoDiscoverTypes( rs );
            }
            return rs;
        }
        catch ( SQLException sqle ) {
            session.getTransactionCoordinator().getJdbcCoordinator().release( st );
            throw sqle;
        }
    }

    该方法执行PreparedStatement,通过autoDiscoverTypes( rs )方法自动匹配查询列的类型。
    org.hibernate.loader.custom.JdbcResultMetadata类:
   
public Type getHibernateType(int columnPos) throws SQLException {
        int columnType = resultSetMetaData.getColumnType( columnPos );
        int scale = resultSetMetaData.getScale( columnPos );
        int precision = resultSetMetaData.getPrecision( columnPos );
 
        int length = precision;
        if ( columnType == Types.CHAR && precision == 0 ) {
            length = resultSetMetaData.getColumnDisplaySize( columnPos );
        }
 
        return factory.getTypeResolver().heuristicType(
                factory.getDialect().getHibernateTypeName(
                        columnType,
                        length,
                        precision,
                        scale
                )
        );
    }

    org.hibernate.dialect.Dialect类
   
// register hibernate types for default use in scalar sqlquery type auto detection
        registerHibernateType( Types.BIGINT, StandardBasicTypes.BIG_INTEGER.getName() );

    hibernate将java.sql.Types.BIGINT对应为StandardBasicTypes.BIG_INTEGER。
    自定义Dialect类,修改java.sql.Types.BIGINT对应的hibernate类型,然后hibernate使用自定义的Dialect。    
public class LocalMySQL5InnoDBDialect extends MySQL5InnoDBDialect {
     
    public LocalMySQL5InnoDBDialect() {
        super();
        registerHibernateType( Types.BIGINT, StandardBasicTypes.LONG.getName() );
    }
}

    自定义Dialect类,修改了hibernate框架本身的类型匹配,目前还未测试出对于其他地方有什么影响,也许这种修改会给自己挖个坑。
分享到:
评论

相关推荐

    Hibernate高级映射实例

    在Java世界中,Hibernate是一个非常流行的持久化框架,它简化了数据库操作,使得开发者可以更加专注于业务逻辑,而不是底层的数据存储。本实例主要探讨的是Hibernate的高级映射技术,包括单向一对一、单向多对一、...

    Java中BigInteger方法总结

    10. **long longValue()**:返回 `BigInteger` 转换为 `long` 类型的值。 11. **BigInteger max(BigInteger val)**:返回两个 `BigInteger` 中较大的那个。 12. **BigInteger min(BigInteger val)**:返回两个 `...

    JAVABigInteger包.pdf

    BigInteger 类提供了一个静态方法 `valueOf(long val)`, 返回一个是指定值的 BigInteger 对象。 运算方法 BigInteger 类提供了多种运算方法来处理 BigInteger 对象。这些方法包括: * `add(BigInteger val)`: ...

    BigInteger

    用java写的BigInteger,主要是实现一个内库

    C#写的BigInteger

    在.NET框架中,标准的数据类型如`int`, `long`等在处理大数据时可能会遇到局限,因为它们有固定的存储范围。为了解决这个问题,`System.Numerics.BigInteger`类被引入,它允许开发者处理任意大的整数。这个类在C#...

    RSA.rar_BigInteger_RSA BigInteger_RSA java biginteger_RSA 类 java

    它可以处理远大于`int`或`long`所能表示的数值,并提供各种算术操作,如加、减、乘、除、模运算,以及位操作。这对于RSA算法来说至关重要,因为它需要处理大素数和它们的乘积。 2. **RSA原理**: RSA算法基于数论中...

    关于Biginteger的分数类期末课程设计

    在Java编程语言中,BigInteger类是用于处理大整数的一种数据类型,它可以处理超过long类型所能表示的最大值的整数。在"关于Biginteger的分数类期末课程设计"这个项目中,你创建了一个分数类,其中分子和分母都是用...

    BigInteger, JS插件脚本

    BigInteger库正是为了解决这个问题,它提供了在JavaScript中操作大整数的能力,支持加减乘除、比较、模运算等多种数学运算。 BigInteger库通常用于需要处理超出JavaScript原生数据类型限制的场景,比如加密算法、...

    java练习_大数运算_BigInteger.pdf

    6. `remainder()` 方法:该方法用于将一个 BigInteger 对象除以另一个 BigInteger 对象,并返回余数。 例如:`n = k.remainder(m);` 在上面的代码中,我们使用了 BigInteger 类的多种方法来实现大数运算。例如,...

    CSharp 4.0 .Net Framework V4.0 BigInteger 结构

    CSharp 4.0 .Net Framework V4.0 BigInteger 结构 C# 4.0 中的 BigInteger 结构是 .NET Framework 4 中的一个重要组件,它用于表示任意大的带符号整数。这个结构位于 System.Numerics 命名空间中,并包含在 System....

    C# 的 BigInteger

    在.NET框架中,`BigInteger`类提供了一个无符号的大整数数据类型,它能处理超过64位整数范围的数值。...通过深入理解和熟练使用`BigInteger`,开发者可以解决许多涉及大整数计算的问题,提升代码的灵活性和功能。

    node-biginteger:java.math.BigInteger的node.js版本

    类方法:BigInteger.fromLong(val) 瓦尔朗 返回:BigInteger 类方法:BigInteger.fromString(val,[radix]) val字符串 radix int,可选,默认值:10 返回:BigInteger 类方法:BigInteger.fromBuffer(信号量...

    BigInteger.js

    JavaScript支持大整数,页面需要进入BigInteger.js。才能使用

    biginteger

    在编程领域,大整数(BigInteger)是一种能够处理超过普通整型变量范围的数值的数据类型。在Java中,BigInteger类提供了这种功能,它允许我们进行任意精度的算术运算,包括加减乘除、模运算以及位操作。而根据题目...

    java-BigInteger-BigDecimal类源码

    这两个类位于`java.math`包下,为开发者提供了超越基本数据类型(如int、long和double)的计算能力。在深入分析`BigInteger`和`BigDecimal`的源代码之前,我们先来理解这两个类的基本概念和用途。 `BigInteger`类:...

    BigInteger_src.zip

    使用这个压缩包中的资源,开发者可以学习如何在C#环境下实现这一过程,从而在自己的项目中实现安全的数据加解密功能。 总结来说,"BigInteger_src.zip"提供了一个在C#环境中使用BigInteger类实现RSA加解密的实例。...

    BigInteger.7z

    在.NET框架中,BigInteger类在`System.Numerics`命名空间下,自.NET Framework 4.0起被引入。在.NET版本2.0中,虽然没有内置的BigInteger支持,但这个资源可能是开发者社区为了扩展.NET 2.0的功能而创建的一个第三方...

    BigInteger_demo.zip

    在Java中,BigInteger类是用于进行任意精度的整数运算,它能够处理超过普通int或long类型所能表示范围的数值。 **BigInteger类详解:** BigInteger类是Java.math包的一部分,设计用来进行大规模整数运算。它提供了...

    big_integer.zip_BigInteger乘_big integer_biginteger 加_biginteger加

    在编程领域,大整数(BigInteger)处理是计算科学中不可或缺的一部分,特别是在处理超过普通整型数据类型范围的数值时。`BigInteger`类通常在Java、Python等编程语言中提供,用于表示任意精度的整数,可以进行大整数...

Global site tag (gtag.js) - Google Analytics