web-dev-qa-db-fra.com

Exception ORA-08103: l'objet n'existe plus lors de l'utilisation de setfetchsize of Hibernate

J'utilise Hibernate. J'ai besoin d'aller chercher environ 1000000 enregistrements et cela entraînera une exception de délai d'attente. J'utilise donc setfetchsize pour 6000 enregistrements, de sorte qu'il distribue l'opération dans plusieurs transactions, chacun des 6000 enregistrements.

Il faudra environ 21 heures pour tout aller chercher.

Mais pendant ce temps, récupérer des enregistrements si quelqu'un supprime un des enregistrements à récupérer, j'obtiens ORA-08103: object no longer exists.

Maintenant, je veux ignorer cet objet qui est supprimé lors de la récupération. Comment puis-je faire ceci?

11
Barney

Très probablement, un curseur est ouvert sur la base d'une table temporaire globale (GTT) créée avec l'option ON COMMIT DELETE ROWS. Et la cause de l'erreur ORA-08103: object no longer exists est l'instruction commit qui a suivi immédiatement après l'instruction delete. Voici un exemple simple:

 SQL> declare
  2    type t_recs is table of number;
  3    l_cur sys_refcursor;    -- our cursor
  4    l_rec t_recs; 
  5  
  6  begin
  7  
  8    -- populating a global temporary table GTT1 with sample data  
  9    insert into GTT1(col)
 10      select level
 11        from dual
 12     connect by level <= 1000;
 13  
 14   open l_cur         -- open a cursor based on data from GTT1
 15    for select col
 16          from GTT1;
 17  
 18    -- here goes delete statement
 19    -- and
 20    commit;  <-- cause of the error. After committing  all data from GTT1 will be
 21              -- deleted and when we try to fetch from the cursor
 22    loop      -- we'll face the ORA-08103 error
 23      fetch l_cur    -- attempt to fetch data which are long gone.
 24       bulk collect into l_rec;
 25      exit when l_cur%notfound;
 26    end loop;
 27  
 28  end;
 29  /


ORA-08103: object no longer exists
ORA-06512: at line 24

La recréation d'une table temporaire globale avec la clause on commit preserve rows permettra d'extraire en toute sécurité des données d'un curseur basé sur cette table sans craindre de faire face à une erreur ORA-08103:.

15
Nick Krasnov

Après avoir lutté une semaine, j'ai finalement résolu le problème:

Solution: Il est fort probable qu'un curseur soit ouvert en fonction d'une table temporaire globale (GTT) créée avec l'option ON COMMIT DELETE ROWS. Et la cause de l'erreur ORA-08103: object n'existe plus est l'instruction de validation qui a suivi immédiatement après l'instruction de suppression. L’équipe DBA n’ayant pas accepté de modifier le GTT comme sur les lignes de conservation de validation, j’ai finalement ajouté une base de code dans la couche de services Java [Implémentation de la transaction Spring - Programmatic]

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;
   }
}
0
user1765387