在Oracle中调用存储过程返回refcursor时出现错误
2011-05-10 03:36:23 DirtiesContextTestExecutionListener [DEBUG] After test method: context [[TestContext@3a363a36 testClass = AccountActivityServiceTest, locations = array<String>['classpath:/com/bnymellon/pwb/pfdetails/service/test/test-application-context.xml'], testInstance = com.bnymellon.pwb.pfdetails.service.test.AccountActivityServiceTest@6d2c6d2c, testMethod = getData@AccountActivityServiceTest, testException = org.springframework.jdbc.UncategorizedSQLException:
### Error updating database. Cause: java.sql.SQLException: ORA-08103: object no longer exists
### The error may involve com.bnymellon.pwb.pfdetails.persistence.AccountActivityMapper.getAccountActivityData-Inline
### The error occurred while setting parameters
### Cause: java.sql.SQLException: ORA-08103: object no longer exists
; uncategorized SQLException for SQL []; SQL state [72000]; error code [8103]; ORA-08103: object no longer exists
; nested exception is java.sql.SQLException: ORA-08103: object no longer exists
我正在使用Spring MyBatis整合项目。 MyBatis的版本是3.0.4
我可以看到程序正在执行。日志如下。
2011-05-10 03:36:16 PreparedStatement [DEBUG] ==> Executing: {call PWMWI.PAM_TRANSACTION_PKG.ACCOUNT_ACTIVITY( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}
2011-05-10 03:36:16 PreparedStatement [DEBUG] ==> Parameters: 1987(Integer), 5627(Integer), null, null, 2010-01-01(Date), 2010-12-31(Date), All Asset Classes(String), [All, PYR](String), (String), null
My Mapper XMl如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bnymellon.pwb.pfdetails.persistence.AccountActivityMapper">
<select id="getAccountActivityData"
parameterType="com.bnymellon.pwb.pfdetails.common.AccountActivityDTO"
statementType="CALLABLE">
{call PWMWI.PAM_TRANSACTION_PKG.ACCOUNT_ACTIVITY(
#{userInstance,mode=IN, jdbcType=INTEGER},
#{accountGroupId,mode=IN,
jdbcType=INTEGER},
#{accountId,mode=IN, jdbcType=VARCHAR},
#{accountId,mode=IN, jdbcType=VARCHAR},
#{startDate,mode=IN,
jdbcType=DATE},
#{endDate,mode=IN, jdbcType=DATE},
#{assetClass,mode=IN, jdbcType=VARCHAR},
#{transactionType,mode=IN,
jdbcType=VARCHAR},
#{cusipId,mode=IN, jdbcType=VARCHAR},
#{ticker,mode=IN, jdbcType=VARCHAR},
#{domainList,mode=OUT,jdbcType=CURSOR,javaType=java.sql.ResultSet,resultMap=aaDataMap})}
</select>
<resultMap type="com.bnymellon.pwb.pfdetails.domain.AccountActivity"
id="aaDataMap">
<result column="TICKER" property="ticker" jdbcType="VARCHAR" />
<result column="CUSIP" property="cusIp" jdbcType="VARCHAR" />
<result column="SECURITY_NAME" property="securityName"
jdbcType="VARCHAR"></result>
<result column="ASSET_CLASS" property="assetClass" jdbcType="VARCHAR" />
<result column="TRADE_DATE" property="tradeDate" jdbcType="DATE" />
<result column="SETTLE_DATE" property="settleDate" jdbcType="DATE" />
<result column="DESCRIPTION" property="description" jdbcType="VARCHAR" />
<result column="RECORD_TYPE" property="description" jdbcType="VARCHAR" />
<result column="ACCOUNT_NUMBER" property="accountNumber"
jdbcType="VARCHAR" />
<result column="QUANTITY" property="shares" jdbcType="VARCHAR" />
<result column="LONG_DESC" property="transDesc" jdbcType="VARCHAR" />
<result column="PORT_NUM" property="indicator" jdbcType="INTEGER" />
<result column="AMOUNT" property="amount" jdbcType="VARCHAR" />
</resultMap>
</mapper>
我使用的是MyBatis 3.0.4版,我的Oracle驱动程序jar是ojdbc14-10.2.0.3.0.jar
过程的IN和OUT参数及其数据类型如下:
P_USER_INST NUMBER IN
P_GROUP_ID NUMBER IN
P_ENTITY_ID CHAR IN
P_ENTITY_NAME VARCHAR2 (30) IN
P_START_DATE DATE IN
P_END_DATE DATE IN
P_ASSETCLASS CHAR IN
P_TRAN_TYPE CHAR IN
P_PRIMARY_ASSET_ID VARCHAR2 IN
P_TICKER VARCHAR2 IN
P_ACCOUNT_DETAIL_CUR REF CURSOR OUT
Java中的我的DTO如下(省略了setter / getter方法)
private Integer userInstance;
private Integer accountGroupId;
private String accountId;
private Date startDate;
private Date endDate;
private String transactionType;
private String ticker;
private String cusipId;
private String assetClass;
private List<AccountActivity> domainList;
任何帮助都非常受欢迎,因为我不知道发生了什么,并且真正坚持这一点。
答案 0 :(得分:4)
我刚刚遇到类似的问题.net而不是Java。
我的问题与基于全局临时表打开游标的事实有关。当我们从“删除行”将GTT更改为“on commit preserve rows”时,它运行正常。
看看它是否适合你?
答案 1 :(得分:0)
这可能是表或数据文件中的损坏,物理或逻辑。 请与您的DBA联系以恢复数据。您可以在http://24x7dba.blogspot.com/2011/08/salvage-data-from-corrupted-oracle.html
找到有关如何从Oracle表中恢复损坏数据的步骤答案 2 :(得分:0)
ORA-8103&#34;对象不再存在&#34;
错误:ORA 8103
原因:自操作开始以来,该对象已被其他用户删除。 操作:删除对象的引用。
ORA-8103报告SQL语句发现了一个不再属于语句中引用的对象的块。 原因 ORA-8103由无效的块类型引起。块头具有无效的块类型,或者块内的块类型不是预期的;例如预期数据块(Type = 6) 但实际的块信息不是数据块(Type!= 6)。 ORA-8103也是由意外的data_object_id引起的,当执行受影响的SQL语句时,它会更改所涉及的对象。
答案 3 :(得分:0)
经过一周的努力,我终于解决了问题:
解决方案:很可能是基于全局临时表(GTT)打开游标,该表是使用ON COMMIT DELETE ROWS选项创建的。并且ORA-08103:对象不再存在的原因错误是紧跟在delete语句之后的commit语句。 DBA团队不同意改变GTT 因为提交保留行所以最后我在Java服务层[实现Spring - 程序化事务]
中添加了代码库package com.test;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
public class StudentJDBCTemplate implements StudentDAO {
private DataSource dataSource;
private JdbcTemplate jdbcTemplateObject;
private PlatformTransactionManager transactionManager;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
}
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
public void create(String name, Integer age, Integer marks, Integer year){
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
String SQL1 = "insert into Student (name, age) values (?, ?)";
jdbcTemplateObject.update( SQL1, name, age);
// Get the latest student id to be used in Marks table
String SQL2 = "select max(id) from Student";
int sid = jdbcTemplateObject.queryForInt( SQL2 );
String SQL3 = "insert into Marks(sid, marks, year) " + "values (?, ?, ?)";
jdbcTemplateObject.update( SQL3, sid, marks, year);
System.out.println("Created Name = " + name + ", Age = " + age);
transactionManager.commit(status);
}
catch (DataAccessException e) {
System.out.println("Error in creating record, rolling back");
transactionManager.rollback(status);
throw e;
}
return;
}
public List<StudentMarks> listStudents() {
String SQL = "select * from Student, Marks where Student.id=Marks.sid";
List <StudentMarks> studentMarks = jdbcTemplateObject.query(SQL,
new StudentMarksMapper());
return studentMarks;
}
}
答案 4 :(得分:0)
就我而言,此错误与全局临时表有关。 在表DDL中,我从“提交删除行时”更改为“提交保留行时”,问题已得到解决。
答案 5 :(得分:0)
创建全局临时表时,如下所示。
CREATE GLOBAL TEMPORARY TABLE table_name(col-1 type, col-2 type, ...) ON COMMIT PRESERVE ROWS