Zarządzanie transakcjami jest możliwe za pomocą adnotacji @Transactonal, @UserTransactional, oraz @SharkTransactional. Adnotacje te możemy używać tylko w klasach zarządzanych przez kontekst aplikacji.
Zaleca się stosowanie adnotacji do zarządzania transakcjami w klasach oznaczonych adnotacją @Service |
@Service public class CustomServiceImpl implements CustomService { @Autowired private StructureService structureService; @Transactional public void addPositionAndOu() { Position p = new Position( "name", "symbol" ); OrganizationalUnit ou = new OrganizationalUnit(); ou.setName( "name" ); ou.setSymbol( "symbol" ); structureService.createPosition( p ); structureService.createOrganizationalUnit( ou ); } public void addPositionAndOuNonTransactional() { Position p = new Position( "name", "symbol" ); OrganizationalUnit ou = new OrganizationalUnit(); ou.setName( "name" ); ou.setSymbol( "symbol" ); structureService.createPosition( p ); structureService.createOrganizationalUnit( ou ); } } |
W powyższym przykładzie funkcja bez adnotacji @Transactional utworzy osobne transakcje dla każdej funkcji save, natomiast w funkcji oznaczonej @Transactional obie operacje będą działać na jednej tej samej transakcji.
public static void execute() { ClientService cs = SpringContext.getBean( ClientService.class ); cs.addPositionAndOu(); } |
Istnieje możliwość manualnego zarządzania transakcjami w przypadkach gdy potrzebujemy większej kontroli lub potrzebujemy ich w obszarze kodu, w którym nie mamy możliwości skorzystania z adnotacji opisanych powyżej.
W tym celu możemy wykorzystać klasę TransactionManagerFactory
TransactionTemplate tt = new TransactionTemplate( TransactionManagerFactory.getHibernateTransactionManager() ); tt.execute( new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult( TransactionStatus status ) { QueryExecutor qe = ComponentFactory.getQueryExecutor(); SQLQuery sql = qe.createSQLQuery( ... ); ... sql.executeUpdate(); } } ); |
Jeżeli potrzebujemy mieć dostęp do obiektu Session od Hibernate, należy TransactionTemplate wykorzysać następująco:
TransactionTemplate tt = new TransactionTemplate( TransactionManagerFactory.getHibernateTransactionManager() ); tt.execute( new SessionAwareTransactionCallbackWithoutResult() { @Override public void doWithSession( Session session ) { session.delete( ... ); } } ); |
final SharkTransactionManager mgr= TransactionManagerFactory.getSharkTransactionManager(); TransactionTemplate tt = new TransactionTemplate( mgr ); tt.execute( new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult( TransactionStatus status ) { SharkTransaction sharkTransaction = mgr.getSharkTransaction(); ... } } ); |
SharkTransactionManager= TransactionManagerFactory.getSharkTransactionManager(); TransactionStatus txStatus = null; try { txStatus = mgr.getTransaction( new DefaultTransactionDefinition() ); SharkTransaction sharkTransaction = mgr.getSharkTransaction(); ...//wykonywanie operacji na transakcji mgr.commit( txStatus ); } catch ( Exception ex ) { mgr.rollback( txStatus ); } |
Klasa com.suncode.pwfl.transaction.support.SharkTransactionTemplate
ułatwia zarządzanie transakcją Shark'ową w czytelny i bezpieczny sposób.
Wszędzie tam, gdzie potrzebujemy transakcję Shark'ową powinniśmy wykorzystywać klasę SharkTransactionTemplate ze względu na łatwiejsze jej użycie. Obsługa kodu transakcyjnego może być skomplikowana i wymaga uważnego traktowania. |
Jeżeli kod wykorzystujący transakcję zwraca wynik, wywołanie będzie wyglądać następująco:
SharkTransactionTemplate tx = new SharkTransactionTemplate(); int result = tx.execute( new SharkTransactionCallback<Integer>() { @Override public Integer doInSharkTransaction( SharkTransaction transaction, TransactionStatus status ) throws Exception { // wykorzystanie transakcji return 1; } } ); |
W przypadku, gdy wywołujemy procedurę która nie zwraca żadnego wyniku, możemy skorzystać z innego callback'u SharkTransactionCallbackWithoutResult
:
SharkTransactionTemplate tx = new SharkTransactionTemplate(); tx.execute( new SharkTransactionCallbackWithoutResult() { @Override public void doInSharkTransactionWithoutResult( SharkTransaction transaction, TransactionStatus status ) throws Exception { // wykorzystanie transakcji } }; |
Domyślna konfiguracja |