sql >> Databáze >  >> RDS >> Oracle

Vraťte A, pokud se B pokazí. jarní bota, jdbctemplate

@Transactional anotace na jaře funguje tak, že váš objekt zabalíte do proxy, která zase obalí metody anotované @Transactional v transakci. Kvůli tomu nebude anotace fungovat na soukromých metodách (jako ve vašem příkladu), protože soukromé metody nelze zdědit => nelze je zabalit (to není pravda, pokud používáte deklarativní transakce s aspectj, pak neplatí níže uvedená upozornění související s proxy).

Zde je základní vysvětlení toho, jak @Transactional jarní magie funguje.

Napsali jste:

class A {
    @Transactional
    public void method() {
    }
}

Ale to je to, co ve skutečnosti získáte, když si vstříknete fazole:

class ProxiedA extends A {
   private final A a;

   public ProxiedA(A a) {
       this.a = a;
   }

   @Override
   public void method() {
       try {
           // open transaction ...
           a.method();
           // commit transaction
       } catch (RuntimeException e) {
           // rollback transaction
       } catch (Exception e) {
           // commit transaction
       }
   }
} 

To má svá omezení. Nefungují s @PostConstruct metody, protože jsou volány před proxy serverem. A i když jste vše nakonfigurovali správně, transakce jsou vráceny zpět pouze při nezaškrtnutém ve výchozím nastavení výjimky. Použijte @Transactional(rollbackFor={CustomCheckedException.class}) pokud potřebujete vrátit zpět nějakou zaškrtnutou výjimku.

Další často se vyskytující upozornění, které znám:

@Transactional metoda bude fungovat pouze tehdy, když ji zavoláte "zvenčí", v následujícím příkladu b() nebude zabalené do transakce:

class X {
   public void a() {
      b();
   }

   @Transactional
   public void b() {
   }
}

Je to také proto, že @Transactional funguje na základě proxy vašeho objektu. V příkladu výše a() zavolá X.b() nejde o vylepšenou "jarní proxy" metodu b() takže k žádné transakci nedojde. Jako náhradní řešení musíte zavolat b() z jiné fazole.

Když narazíte na některé z těchto upozornění a nemůžete použít navrhované řešení (označte metodu jako nesoukromou nebo zavolejte b() z jiného bean) můžete použít TransactionTemplate místo deklarativních transakcí:

public class A {
    @Autowired
    TransactionTemplate transactionTemplate;

    public void method() {
        transactionTemplate.execute(status -> {
            A();
            B();
            return null;
        });
    }

...
} 

Aktualizovat

Odpověď na aktualizovanou otázku OP pomocí výše uvedených informací.

Která metoda by měla být anotována pomocí @Transactional:changes()? databaseChanges()?

@Transactional(rollbackFor={Exception.class})
public void changes() throws Exception {
    someLogicBefore();
    databaseChanges();
    someLogicAfter();
}

Ujistěte se, že changes() je voláno „zvenčí“ beanu, nikoli ze samotné třídy a po vytvoření instance kontextu (např. toto není afterPropertiesSet() nebo @PostConstruct anotovaná metoda). Uvědomte si, že ve výchozím nastavení jarní rollback transakce pouze pro nekontrolované výjimky (zkuste být konkrétnější v seznamu rollbackFor kontrolovaných výjimek).



  1. problém s python manage.py migrate -> Žádný modul s názvem psycopg2

  2. jak převést csv na tabulku v oracle

  3. Najděte závislé objekty pro tabulku nebo pohled

  4. Jak transponovat řádky tabulky mysql do sloupců