Используя Spring JDBC для хранимой процедуры Oracle, я получаю ORA-02055, когда SP выбрасывает ORA-20118 - PullRequest
2 голосов
/ 01 февраля 2010

ORA-20118 - это пользовательское исключение из хранимой процедуры. Хранимая процедура прекрасно работает от разработчика PL-SQL, поэтому проблема в Spring. Что мне нужно сделать, это заставить Spring откатить SP, когда он получает исключение ORA-20118 от SP. Как я могу это сделать? или, может быть, просто получить весну, чтобы правильно обработать возвращающийся код 20118. Это тоже сработало бы.

Управление транзакциями не выполняется.

Да код:

@Repository    
public class ProgramMaintenance extends StoredProcedure {    
//bunch of static final param names go here    

@Autowired(required = true)    
public ProgramMaintenance(@Qualifier("osirisDataSource") final DataSource ds) {    
  super(ds, SQL);    
  OracleStoredProcedureExceptionHandler exceptionHandler = new   OracleStoredProcedureExceptionHandler();    
        exceptionHandler.setDataSource(ds);    
        this.getJdbcTemplate().setExceptionTranslator(exceptionHandler);    
        addParameters();    
        this.setFunction(false);    
        compile();    
    }
public void execute( //parameters ) { 
//Put the input map together here
execute(inputMap);
}

Итак, вот обработчик исключений вместе с примечаниями о том, что происходит:

public class OracleStoredProcedureExceptionHandler extends   SQLErrorCodeSQLExceptionTranslator { 
protected DataAccessException customTranslate(String task, String sql, SQLException sqlex) {
        if (logger.isDebugEnabled()) {
            logger.debug("customTranslate(String, String, SQLException) - start"); //$NON-NLS-1$
        }

            //The error code at this point is ORA-02055 with the cause as ORA-20118,
            //So, the case statement drops straight through.

        switch (sqlex.getErrorCode()) {
            case 20113 : return new ProgramNotAtCampusException(task + " " +sql,  sqlex);

            case 20118 : return new ProgramNotApprovedForStateOfResidence(task + " " +sql,  sqlex);

            default: return null;
        }

    }

И трассировка стека:

org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{call isis.program_maintenance.program_maintenance(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}]; nested exception is java.sql.SQLException: ORA-02055: distributed update operation failed; rollback required
ORA-20118: VALIDATION ERROR:This program is not approved for the state this student resides in.
ORA-06512: at "ISIS.APPLY_WEB_INTEGRATION", line 372
ORA-06512: at "ISIS.APPLY_WEB_INTEGRATION", line 1332
ORA-06512: at "ISIS.APPLY_WEB_INTEGRATION", line 2842
ORA-06512: at "ISIS.PROGRAM_MAINTENANCE", line 66
ORA-06512: at line 1

    at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:97)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:952)
    at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:985)
    at org.springframework.jdbc.object.StoredProcedure.execute(StoredProcedure.java:117)
    at com.apollo.aw.dao.storedProcedures.programMaintenance.ProgramMaintenance.execute(ProgramMaintenance.java:125)
    at test.eval.dao.storedprocedures.programMaintenance.TestProgramMaintenance.testExecuteForORA20118(TestProgramMaintenance.java:64)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at junit.framework.TestCase.runTest(TestCase.java:168)
    at junit.framework.TestCase.runBare(TestCase.java:134)
    at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:76)
    at junit.framework.TestResult$1.protect(TestResult.java:110)
    at junit.framework.TestResult.runProtected(TestResult.java:128)
    at junit.framework.TestResult.run(TestResult.java:113)
    at junit.framework.TestCase.run(TestCase.java:124)
    at junit.framework.TestSuite.runTest(TestSuite.java:232)
    at junit.framework.TestSuite.run(TestSuite.java:227)
    at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

Ответы [ 4 ]

1 голос
/ 01 февраля 2010

Что мне нужно сделать, это заставить Spring откатить SP, когда он получит исключение ORA-20118 от SP.

Для декларативных транзакций вы можете обратиться к этому разделу о правилах отката. Короче говоря, просто сгенерируйте исключение, которое не попадет в блок try / catch.

0 голосов
/ 02 февраля 2010

Не волнуйся, будь счастлив. Если Oracle вызывает исключение, любые незавершенные изменения, сделанные этим вызовом, будут автоматически откатываться. Не имеет значения, является ли этот вызов вставкой, обновлением, удалением, слиянием или сохраненным вызовом процедуры, оператор не выполнен, и атомарная природа вызова требует, чтобы состояние базы данных было восстановлено до точки до начала вызовов.

> create table test (id number);

Table created.
> create or replace procedure ins_test is
08:42:46   2  begin
08:42:48   3    insert into test values (10);
08:42:55   4    raise too_many_rows;
08:43:00   5  end;
08:43:01   6  /

Procedure created.
> exec ins_test;
BEGIN ins_test; END;

*
ERROR at line 1:
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "GARY.INS_TEST", line 4
ORA-06512: at line 1

> select * from test;

no rows selected
0 голосов
/ 01 февраля 2010

И правильный ответ ... сам тест был ошибочным, и Spring поступил правильно ... SIGH Это:

 @Test(expected=ProgramNotAtCampusException.class)

не работал правильно, однако, упаковав его в блок try catch и игнорируя ошибку, работает просто отлично. SIGH .

0 голосов
/ 01 февраля 2010

На первый взгляд все выглядит так, как должно. Можете ли вы опубликовать записи spring-config.xml для менеджера транзакций для этого источника данных?

По умолчанию экземпляры RuntimeException вызывают откат в Spring. Существует несколько программных способов отката (но у менеджера транзакций могут быть установлены наиболее распространенные атрибуты, чтобы избежать такого рода кода:

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

Вы должны прочитать документы Spring на Управление транзакциями для подробного обзора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...