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?
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:
.
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;
}
}