java findpage 方法_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 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 Page findPage(Class clasz,final Page page, final String sql, final Map 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 findPage(Page 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 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 PreparedStatement, advance to the first result and return SQL ResultSet.

*/

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框架本身的类型匹配,目前还未测试出对于其他地方有什么影响,也许这种修改会给自己挖个坑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值