日期:2014-05-16 浏览次数:20509 次
使用Spring JDBC对Oracle10g进行数据库分页的时候出现了异常,错误信息如下:
?
[ERROR]2971656-2009-05-1815:38:24- [com.ieslab.idp.datamaint.service.impl.DataGridServiceImpl. buildGrid(DataGridServiceImpl.java: 171)]-[]-org.springframework.jdbc.UncategorizedSQLException: StatementCallback; uncategorized SQLException for SQL [select * from (select temp.* ,ROWNUM num from ( select * from idp_pub_m.厂站_VW) temp where ROWNUM <= 4 ) where num > 0]; SQL state [null]; error code [0]; Invalid scale size. Cannot be less than zero; nested exception is java.sql.SQLException: Invalid scale size. Cannot be less than zero?
上面错误中,进行的操作是从一个视图中查询数据并进行分页操作,当单独执行:
select temp.* ,ROWNUM num from ( select * from idp_pub_m.厂站_VW) temp where ROWNUM <= 4?
时,是没有错误的,可以成功执行。有网友说是Oracle10g中对返回的结果集中数据精度的定义和9i中不同;例如同样是
?
select count(*) from ......
?
语句,在oracle 10g中使用Spring JDBC操作时就会有问题,异常信息同样是 java.sql.SQLException: Invalid scale size. Cannot be less than zero;将SQL语句写为
?
select count(*)+0 from ......
?
就可以解决。
?
这是另一个网友aggie2000 给出的解答,贴于此处,留作备忘。呵呵!
原帖地址是http://forum.springsource.org/showthread.php?t=19848
?
I have been dealing with the same problem (SQLException - "Invalid
scale size. Cannot be less than zero") and believe I have arrived at a
better solution for those who wish to use the Spring API as much as
possible.
The basic problem, as I understand it, is that there is an
incompatibility between Oracle and the standard CachedRowSet
implementation (CachedRowSetImpl) of Java 1.5. Spring uses this
implementation by default when you call queryForRowSet(...). However,
this does not mean that you cannot use SqlRowSet. The SqlRowSet class
doesn't know anything about the implementation of the CachedRowSet
interface that you're using. The class that is actually utilizing the
CachedRowSetImpl class is the ResultSetExtractor... more specifically,
the SqlRowSetResultSetExtractor (this is used by Spring when you call
queryForRowSet).
In order to achieve the same result (returning a Spring SqlRowSet), you
can pass in your own ResultSetExtractor to the query(...) methods
(*not* queryForRowSet) that take a ResultSetExtractor as a parameter.
What I did was just clone the SqlRowSetResultSetExtractor and instead
of using the standard CachedRowSetImpl class, I replaced it with
Oracle's CachedRowSet implementation. This way, when the ResultSet is
mapped to a CachedRowSet, it uses Oracle's implementation to do so and
thus the incompatibility is eliminated. Here is my ResultSetExtractor
class that does just that...
-------------------------
package com.yada.yada.yada; import java.sql.ResultSet; import java.sql.SQLException; import javax.sql.rowset.CachedRowSet; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.support.rowset.ResultSetW rappingSqlRowSet; import org.springframework.jdbc.support.rowset.SqlRowSet; import oracle.jdbc.rowset.OracleCachedRowSet; public class SqlRowSetOracleResultSetExtractor implements ResultSetExtractor { public Object extractData(ResultSet rs) throws SQLException { return createSqlRowSet(rs); } /** * Create a SqlRowSet that wraps the given ResultSet, * representing its data in a disconnected fashion. * <p>This implementation creates a Spring ResultSetWrappingSqlRowSet * instance that wraps a standard JDBC CachedRowSet instance. * Can be overridden to use a different implementation. * @param rs the original ResultSet (connected) * @return the disconnected SqlRowSet * @throws SQLException if thrown by JDBC methods * @see #newCachedRowSet * @see org.spr