使用数据库为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框架本身的类型匹配,目前还未测试出对于其他地方有什么影响,也许这种修改会给自己挖个坑。
分享到:
相关推荐
在Java世界中,Hibernate是一个非常流行的持久化框架,它简化了数据库操作,使得开发者可以更加专注于业务逻辑,而不是底层的数据存储。本实例主要探讨的是Hibernate的高级映射技术,包括单向一对一、单向多对一、...
10. **long longValue()**:返回 `BigInteger` 转换为 `long` 类型的值。 11. **BigInteger max(BigInteger val)**:返回两个 `BigInteger` 中较大的那个。 12. **BigInteger min(BigInteger val)**:返回两个 `...
BigInteger 类提供了一个静态方法 `valueOf(long val)`, 返回一个是指定值的 BigInteger 对象。 运算方法 BigInteger 类提供了多种运算方法来处理 BigInteger 对象。这些方法包括: * `add(BigInteger val)`: ...
用java写的BigInteger,主要是实现一个内库
在.NET框架中,标准的数据类型如`int`, `long`等在处理大数据时可能会遇到局限,因为它们有固定的存储范围。为了解决这个问题,`System.Numerics.BigInteger`类被引入,它允许开发者处理任意大的整数。这个类在C#...
它可以处理远大于`int`或`long`所能表示的数值,并提供各种算术操作,如加、减、乘、除、模运算,以及位操作。这对于RSA算法来说至关重要,因为它需要处理大素数和它们的乘积。 2. **RSA原理**: RSA算法基于数论中...
在Java编程语言中,BigInteger类是用于处理大整数的一种数据类型,它可以处理超过long类型所能表示的最大值的整数。在"关于Biginteger的分数类期末课程设计"这个项目中,你创建了一个分数类,其中分子和分母都是用...
BigInteger库正是为了解决这个问题,它提供了在JavaScript中操作大整数的能力,支持加减乘除、比较、模运算等多种数学运算。 BigInteger库通常用于需要处理超出JavaScript原生数据类型限制的场景,比如加密算法、...
6. `remainder()` 方法:该方法用于将一个 BigInteger 对象除以另一个 BigInteger 对象,并返回余数。 例如:`n = k.remainder(m);` 在上面的代码中,我们使用了 BigInteger 类的多种方法来实现大数运算。例如,...
CSharp 4.0 .Net Framework V4.0 BigInteger 结构 C# 4.0 中的 BigInteger 结构是 .NET Framework 4 中的一个重要组件,它用于表示任意大的带符号整数。这个结构位于 System.Numerics 命名空间中,并包含在 System....
在.NET框架中,`BigInteger`类提供了一个无符号的大整数数据类型,它能处理超过64位整数范围的数值。...通过深入理解和熟练使用`BigInteger`,开发者可以解决许多涉及大整数计算的问题,提升代码的灵活性和功能。
类方法:BigInteger.fromLong(val) 瓦尔朗 返回:BigInteger 类方法:BigInteger.fromString(val,[radix]) val字符串 radix int,可选,默认值:10 返回:BigInteger 类方法:BigInteger.fromBuffer(信号量...
JavaScript支持大整数,页面需要进入BigInteger.js。才能使用
在编程领域,大整数(BigInteger)是一种能够处理超过普通整型变量范围的数值的数据类型。在Java中,BigInteger类提供了这种功能,它允许我们进行任意精度的算术运算,包括加减乘除、模运算以及位操作。而根据题目...
这两个类位于`java.math`包下,为开发者提供了超越基本数据类型(如int、long和double)的计算能力。在深入分析`BigInteger`和`BigDecimal`的源代码之前,我们先来理解这两个类的基本概念和用途。 `BigInteger`类:...
使用这个压缩包中的资源,开发者可以学习如何在C#环境下实现这一过程,从而在自己的项目中实现安全的数据加解密功能。 总结来说,"BigInteger_src.zip"提供了一个在C#环境中使用BigInteger类实现RSA加解密的实例。...
在.NET框架中,BigInteger类在`System.Numerics`命名空间下,自.NET Framework 4.0起被引入。在.NET版本2.0中,虽然没有内置的BigInteger支持,但这个资源可能是开发者社区为了扩展.NET 2.0的功能而创建的一个第三方...
在Java中,BigInteger类是用于进行任意精度的整数运算,它能够处理超过普通int或long类型所能表示范围的数值。 **BigInteger类详解:** BigInteger类是Java.math包的一部分,设计用来进行大规模整数运算。它提供了...
在编程领域,大整数(BigInteger)处理是计算科学中不可或缺的一部分,特别是在处理超过普通整型数据类型范围的数值时。`BigInteger`类通常在Java、Python等编程语言中提供,用于表示任意精度的整数,可以进行大整数...