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
@Transactionalwywołania metod usług są przechwytywane przezTransactionInterceptorAspekt. -
TransactionIntreceptordeleguje zarządzanie transakcjami do aktualnie skonfigurowanejAbstractPlatformTransactionManagerimplementacja (JpaTransactionManagerw twoim przypadku). -
JpaTransactionManagerpowiąż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. -
JpaTransactionManagerpo prostu używaEntityManagerTransaction 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.JdbcTransactionpołą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 (
DataSourceConnectionProviderw 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.