To wcale nie jest skomplikowane.
-
Po pierwsze, musisz zrozumieć, że menedżer transakcji Spring jest tylko abstrakcją zarządzania transakcjami. W Twoim przypadku faktyczne transakcje odbywają się na poziomie połączenia JDBC.
-
Wszystkie
@Transactional
wywołania metod usług są przechwytywane przezTransactionInterceptor
Aspekt. -
TransactionIntreceptor
deleguje zarządzanie transakcjami do aktualnie skonfigurowanejAbstractPlatformTransactionManager
implementacja (JpaTransactionManager
w twoim przypadku). -
JpaTransactionManager
powiąże bieżącą działającą transakcję Spring z EntityManager, więc wszystkie DAO uczestniczące w bieżącej transakcji współdzielą ten sam kontekst trwałości. -
JpaTransactionManager
po prostu używaEntityManager
Transaction API do kontrolowania transakcji:EntityTransaction tx = txObject.getEntityManagerHolder().getEntityManager().getTransaction(); tx.commit();
Interfejs API transakcji JPA po prostu deleguje wywołanie do podstawowych metod zatwierdzania/wycofywania połączenia JDBC Connection.
-
Po zakończeniu transakcji (zatwierdzenie/wycofanie),
org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction
połączenia:transactionCoordinator().getTransactionContext().managedClose();
co wyzwala zamknięcie sesji hibernacji (menedżera jednostek).
-
Bazowe połączenie JDBC jest zatem również wyzwalane do zamknięcia:
jdbcCoordinator.close();
-
Hibernate ma logiczny uchwyt połączenia JDBC:
@Override public Connection close() { LOG.tracev( "Closing JDBC container [{0}]", this ); if ( currentBatch != null ) { LOG.closingUnreleasedBatch(); currentBatch.release(); } cleanup(); return logicalConnection.close(); }
-
Połączenie logiczne deleguje wywołanie zamknięcia do aktualnie skonfigurowanego dostawcy połączenia (
DataSourceConnectionProvider
w twoim przypadku), która po prostu wywołuje metodę zamykania połączenia JDBC:@Override public void closeConnection(Connection connection) throws SQLException { connection.close(); }
-
Podobnie jak w przypadku każdego innego DataSource w puli połączeń, zamknięcie połączenia JDBC po prostu zwraca połączenie do puli i nie zamyka fizycznego połączenia z bazą danych. Dzieje się tak, ponieważ DataSource puli połączeń zwraca serwer proxy połączenia JDBC, który przechwytuje wszystkie wywołania i deleguje zamykanie do logiki obsługi puli połączeń.
Pamiętaj, że w przypadku transakcji RESOURCE_LOCAL należy również ustawić hibernate.connection.provider_disables_autocommit
właściwość, jeśli autocommit
kontrola została wyłączona przez pulę połączeń. W ten sposób połączenia z bazą danych będą uzyskiwane leniwie przed wykonaniem zapytania SQL lub opróżnieniem kontekstu trwałości.