问题发生的环境: 在springMvc+mybatis框架中,调用oracle的存储过程时,碰到的一个这样的异常:
org.springframework.jdbc.UncategorizedSQLException: ### Error querying database. Cause: java.sql.SQLException: ORA-08103: 对象不再存在 ### The error may exist in com/coscon/wechat/oracle/mapper/VgmCntrMapper.xml ### The error may involve com.coscon.wechat.oracle.mapper.VgmCntrMapper.findVgmInfoByBkgNo ### The error occurred while handling results ### SQL: {call SP_VGM_CNTR_QUERY(?, ?, ?, ? ) } ### Cause: java.sql.SQLException: ORA-08103: 对象不再存在 ; uncategorized SQLException for SQL []; SQL state [72000]; error code [8103]; ORA-08103: 对象不再存在 ; nested exception is java.sql.SQLException: ORA-08103: 对象不再存在
问题的原因
调用的oracle存储过程【sp】中,存在一个事物级别的临时表,例如:
create global temporary table TEMP_VGM_CNTR ( vgm_uuid VARCHAR2(40), cntr_num VARCHAR2(20), cntr_type VARCHAR2(4), bkg_num VARCHAR2(20), bl_num VARCHAR2(20), vgm_tare_wt NUMBER(12,3), vgm_wt NUMBER(12,3), vgm_wt_unit VARCHAR2(10), excel_logs VARCHAR2(4000) ) on commit delete rows;
事物级临时表,当发生事物提交的时候,临时表中的数据就会被清空。
对于返回游标的存储过程来说,放在临时表中的数据就会被清空。那么在Java代码去调用存储过程时候,如果没有特殊的事物配置,在调用完存储过程后,就代表事物的结束,数据自然就没有了。so,程序就产生了“ORA-08103: 对象不再存在”的异常。
问题的解决
在springMVC+mybatis的数据库配置中添加事物处理机制:
<bean id="oracleTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--代表数据库环境:oracle--> <property name="dataSource" ref="oracleDataSource" /> <qualifier value="ebTransactionManager"/> <!-- <property name="typeAliasesPackage" value="com.coscon.wechat.oracle.entity" /> --> </bean> <bean id="oracleSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!---具体数据库配置--> <property name="dataSource" ref="oracleDataSource" /> </bean> <!-- 可通过注解控制事务,即事物处理的机制 --> <tx:annotation-driven transaction-manager="oracleTransactionManager"/> <!-- Mapper接口所在包名,Spring会自动查找其下的Mapper --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="oracleSessionFactory"/> <property name="basePackage" value="com.coscon.wechat.oracle.mapper" /> </bean>
注意:
由于项目中会出现配置了多个数据源的情况,注解事务时显示指明事务由谁管理。例如:
<qualifier value="ebTransactionManager"/>
然后在你调用的方法的service层,添加事物注解:
@Override @SuppressWarnings("unchecked") @Transactional(value = "ebTransactionManager",propagation= Propagation.REQUIRED) public List<VgmCntr> findVgmInfoByBkgNo(String bkgNum, String blNum, String cntrNum) { Map<String, Object> map=new HashMap<String, Object>(); map.put("bkgNum", bkgNum); map.put("blNum", null); map.put("cntrNum", null); vgmCntrMapper.findVgmInfoByBkgNo(map); List<VgmCntr> list=(List<VgmCntr>)map.get("rows"); return list; }