正常使用的功能突然異常了,是天災(zāi)還是人禍阴汇?——人禍数冬。
過程
今天一個很正常的查詢功能突然異常了,前臺顯示不了數(shù)據(jù)搀庶,后臺報錯:Caused by: java.sql.SQLException: Fail to convert to internal representation拐纱。那我們就從這個異常入手吧。
異常明細(xì):
Caused by: java.sql.SQLException: Fail to convert to internal representation
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208)
at oracle.jdbc.driver.CharCommonAccessor.getLong(CharCommonAccessor.java:239)
at oracle.jdbc.driver.OracleResultSetImpl.getLong(OracleResultSetImpl.java:558)
at oracle.jdbc.driver.OracleResultSet.getLong(OracleResultSet.java:1575)
at org.apache.commons.dbcp.DelegatingResultSet.getLong(DelegatingResultSet.java:278)
at org.apache.commons.dbcp.DelegatingResultSet.getLong(DelegatingResultSet.java:278)
at org.apache.ibatis.type.LongTypeHandler.getNullableResult(LongTypeHandler.java:37)
at org.apache.ibatis.type.LongTypeHandler.getNullableResult(LongTypeHandler.java:26)
at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:55)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getPropertyMappingValue(DefaultResultSetHandler.java:393)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.applyPropertyMappings(DefaultResultSetHandler.java:367)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getRowValue(DefaultResultSetHandler.java:341)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForSimpleResultMap(DefaultResultSetHandler.java:294)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:269)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:239)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:153)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:60)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:73)
at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:60)
at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:267)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:137)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:96)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:77)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:108)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:102)
at sun.reflect.GeneratedMethodAccessor239.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:358)
... 97 more
重點在:at oracle.jdbc.driver.CharCommonAccessor.getLong(CharCommonAccessor.java:239)地来,看來是類型轉(zhuǎn)換時出錯了。通過反編譯ojdbc.jar定位到具體的代碼:
package oracle.jdbc.driver;
abstract class CharCommonAccessor extends Accessor
{
long getLong(final int n) throws SQLException {
long long1 = 0L;
if (this.rowSpaceIndicator == null) {
DatabaseError.throwSqlException(21);
}
if (this.rowSpaceIndicator[this.indicatorIndex + n] != -1) {
try {
long1 = Long.parseLong(this.getString(n).trim());
}
catch (NumberFormatException ex) {
DatabaseError.throwSqlException(59);
}
}
return long1;
}
}
在String轉(zhuǎn)換Long的時候熙掺,捕獲了一個異常未斑,拋出異常代碼為“59”,那我們在看一下59代表什么币绩。
package oracle.jdbc.driver;
public class DatabaseError
{
public static final int EOJ_CONVERSION_JAVA_ERROR = 59;
}
大意是轉(zhuǎn)換java類型時錯誤蜡秽。
既然是long類型轉(zhuǎn)換異常了,那我們就在數(shù)據(jù)庫執(zhí)行了這個語句缆镣,重點關(guān)注 “數(shù)據(jù)庫:varchar > Java:long”的字段芽突,發(fā)現(xiàn)在數(shù)據(jù)庫中,PID字段為varchar(32)董瞻,但是在代碼中寞蚌,它是long類型,注意有幾個值已經(jīng)明顯超出了Long.MAX_VALUE钠糊,判斷在此出現(xiàn)了轉(zhuǎn)換異常挟秤。修改后,功能恢復(fù)正常抄伍。
總結(jié)
這次異常的原因艘刚,首先是因為在處理之前的異常時,人為修改了生產(chǎn)表數(shù)據(jù)截珍;其次是數(shù)據(jù)庫的數(shù)據(jù)類型沒有和代碼中保持一致攀甚,在設(shè)計數(shù)據(jù)庫和定義代碼數(shù)據(jù)類型時偷懶了箩朴。