Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
If Hibernate throws UnknownServiceException while a transaction is completing, it could not find an internal service in the service registry. For the message naming org.hibernate.stat.spi.StatisticsImplementor, the failure often surfaces in post-transaction cleanup; it does not by itself prove that the database transaction or SQL failed. First check whether a Session crossed thread boundaries or the SessionFactory was closed while work was still running. Use one session per unit of work, finish that work before closing the factory, and then investigate session context, dependency versions, or custom service registration.
What the exception means
Hibernate’s service registry holds runtime infrastructure used by the ORM. UnknownServiceException means a requested service role was not available to the registry. See the ServiceRegistry API and Hibernate service package documentation.
Read the complete message, especially the class name inside brackets. The commonly reported form is:
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →org.hibernate.service.UnknownServiceException:
Unknown service requested [org.hibernate.stat.spi.StatisticsImplementor]
That requested role concerns statistics. A historical report shows the exception arising along a transaction-completion path through JdbcTransaction.afterTransactionCompletion, TransactionCoordinatorImpl.afterTransaction, and SessionFactoryImpl.getStatistics, after connection-pool cleanup begins. It is an example, not a universal stack trace: the reported stack trace.
#1 Best Overall
“When transaction is completed” identifies where the problem became visible, not necessarily where it began. Hibernate may still run callbacks and cleanup after commit or rollback. If the factory or registry has already been closed, or session work is happening in an invalid thread or context, that later service lookup can fail. This is not, on its own, evidence of invalid SQL, a rejected database transaction, or a mapping error.
Start with session and factory lifecycles
The central distinction is simple: share the SessionFactory, not a Session. Hibernate documents the factory as thread-safe and suitable for application-wide use; a session is not thread-safe and should be scoped to a request, conversation, or unit of work. See the Hibernate transaction and concurrency guidance. The current SessionFactory API likewise describes obtaining sessions from a typically shared factory.
- Look for premature shutdown. Search for
sessionFactory.close()and code that closes a service registry. Check whether tests, redeployment, a batch job, or an application shutdown path can close it while tasks are still committing. - Look for shared sessions. Check static fields, singletons, reusable worker objects, and task arguments. A session created in a request must not be handed to an executor or asynchronous callback.
- Check ownership and order. The thread doing the database work should own the session and complete its transaction before closing the session. Close the factory only after all work is done.
Unsafe patterns include storing a session in a static field, keeping one session on a worker object used concurrently, or passing a session obtained from getCurrentSession() to another thread.
Use one session for each unit of work
For a manually managed worker or standalone application, create and close the session inside that unit of work. Keep the factory alive for the application’s persistence configuration.
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
processJob(session, job);
tx.commit();
} catch (RuntimeException e) {
if (tx != null) {
try {
tx.rollback();
} catch (RuntimeException rollbackFailure) {
e.addSuppressed(rollbackFailure);
}
}
throw e;
} finally {
session.close();
}
This pattern makes ownership visible: the session is opened for the work, transaction completion happens before session closure, and rollback is attempted if the work fails. Preserve the first exception; a rollback or close failure should not silently replace the original cause. Where Spring, Jakarta EE, or another framework already manages transactions and sessions, use its supported transaction boundary rather than mixing manual lifecycle management into it.
If the work runs on an executor
Create the session inside each task; never capture and reuse a session from the submitting thread. For example:
executor.submit(() -> {
try (Session session = sessionFactory.openSession()) {
Transaction tx = session.beginTransaction();
try {
processJob(session, job);
tx.commit();
} catch (RuntimeException e) {
if (tx.isActive()) {
tx.rollback();
}
throw e;
}
}
});
Arrange shutdown so new work stops, submitted work finishes or is handled as cancelled, active transactions complete or roll back, and worker sessions close before the factory does. A typical outline is:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteexecutor.shutdown();
if (!executor.awaitTermination(timeout, unit)) {
executor.shutdownNow();
}
sessionFactory.close();
Choose the timeout for your application and handle interruption and tasks that do not terminate. Do not close the factory merely because one transaction has completed. This ordering matters in tests too: teardown must not close Hibernate while asynchronous assertions or background work are still using it.
Check getCurrentSession() and thread-bound context
getCurrentSession() is not a general-purpose way to obtain a session that can travel between threads. It relies on a configured current-session context and its lifecycle rules. The API describes a contextually scoped session controlled by CurrentSessionContext in the SessionFactory documentation.
Rank #4
For legacy configurations such as current_session_context_class=thread, establish who obtains or binds the session, begins the transaction, commits or rolls back, unbinds, and closes. Verify the work stays on that thread. Thread-pool reuse, asynchronous callbacks, listeners, or a request handing work to an executor can break assumptions about thread-local state. Start a new session and transaction inside the worker, or use a framework-supported asynchronous transaction arrangement.
Trace the failure before changing configuration
- Capture the full log and cause chain. Record the exact requested service, the first exception, the Hibernate and Java versions, the framework in use, the thread performing the work, and whether shutdown or redeployment occurred near the error. A later cleanup exception can obscure an earlier connection failure, timeout, interruption, or session error.
- Log factory and worker lifecycle. Log factory creation and closure, task start and finish, and thread names. If factory closure precedes worker completion, correct shutdown ordering.
- Check session identity. In diagnostic logging, compare
System.identityHashCode(session)andThread.currentThread().getName(). The same session identity appearing concurrently on multiple threads is a strong warning. - Run a serialized diagnostic. Temporarily run one worker, perform the work synchronously, remove shared session state, and delay factory shutdown until all work finishes. If the error disappears, concurrency or lifecycle ordering becomes more likely.
Do not treat a line saying an exception was swallowed during cleanup as proof the issue is harmless. Preserve and inspect the original failure as well as any later cleanup exception.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsCheck dependencies and custom integrations if lifecycles are sound
If no session is shared and the factory remains open through completion, verify that the runtime contains a consistent set of Hibernate modules. Older applications may accidentally combine multiple hibernate-core versions, mismatched Hibernate modules, container-provided and application-bundled Hibernate, or incompatible persistence APIs.
mvn dependency:tree -Dincludes=org.hibernate
./gradlew dependencies --configuration runtimeClasspath
Check the deployed runtime classpath, not only the build file. If you use custom integrations, inspect Integrator and ServiceContributor implementations, META-INF/services registrations, and custom statistics or transaction services. Hibernate supports pluggable services, so an incomplete or conflicting registration can affect what a registry can provide; see the service package documentation.
The package name and stack frames in older reports reflect older Hibernate internals. Current versions may have different implementation details and configuration behavior. Verify any setting or integration advice against the exact version deployed; the current service-registry documentation explains the general concept, not every legacy version’s behavior.
Quick Recap
Common fixes that are not enough
- Changing to
openSession()by itself: it helps only if explicit ownership is needed and you also manage transaction, rollback, and closure correctly. - Disabling statistics: the requested service name makes statistics configuration worth checking against the exact Hibernate release, but disabling statistics is not a universal fix for a closed registry or lifecycle race and may remove useful diagnostics.
- Catching and ignoring the exception: this hides evidence and can leave the original transaction or cleanup failure unresolved.
- Increasing the connection-pool size or restarting: neither repairs a session shared across threads or a factory closed before work finishes.
Production checklist
- One long-lived
SessionFactoryper persistence configuration. - A separate session per request or unit of work; no concurrent session sharing.
- Session work and transaction completion stay within the intended thread and context.
- Rollback is attempted on failure, and the original exception is preserved.
- Sessions close after commit or rollback.
- Workers finish before the factory and its registry are closed.
- Hibernate modules and runtime classpath are consistent.
- The full cause chain and exact requested service are recorded.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.

