hibernate SessionFactory
hibernate SessionFactory
Session
A typical transaction should use the following idiom:
Session sess = factory.openSession(); |
Session load vs get
get()
loads the data as soon as it’s called whereasload()
returns a proxy object and loads data only when it’s actually required, soload()
is better because it support lazy loading.- Since
load()
throws exception when data is not found, we should use it only when we know data exists. - We should use
get()
when we want to make sure data exists in the database.
load
- It will always return a “proxy” (Hibernate term) without hitting the database. In Hibernate, proxy is an object with the given identifier value, its properties are not initialized yet, it just look like a temporary fake object.
- If no row found , it will throws an ObjectNotFoundException.
Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists. This method might return a proxied instance that is initialized on-demand, when a non-identifier method is accessed.
Means load
method first check the cache if the fully initialize object
is present there and if yes returns that object else it returns the proxy(A proxy is a class that delegates to another object. Initially, when it's not initialized, it contains just the primary key. When you call a method, as the Javadoc says, it initializes, by loading the actual entity from the database, and the delegates to this loaded entity) of that object by `assuming that instance exists'.
get
- It always hit the database and return the real object, an object that represent the database row, not proxy.
- If no row found , it return null.
Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance. (If the instance is already associated with the session, return that instance. This method never returns an uninitialized instance.)
Means get
method first check the cache if the fully initialize object
is present there if yes return that object otherwise it hits the database to get the object
and returns the same after saving it in the cache space.
https://stackoverflow.com/questions/46144731/hibernate-session-load-vs-session-get
https://www.journaldev.com/3472/hibernate-session-get-vs-load-difference-with-examples
ThreadSafe
Session is not intended that implementors be threadsafe. Instead each thread/transaction should obtain its own instance from a SessionFactory.
A SessionFactory
is an expensive-to-create, threadsafe object intended to be shared by all application threads. It is created once, usually on application startup, from a Configuration
instance.
A Session
is an inexpensive, non-threadsafe object that should be used once, for a single request, a conversation, single unit of work, and then discarded. A Session
will not obtain a JDBC Connection
(or a Datasource
) unless it is needed, hence consume no resources until used.
Get current Session Vs. Open Session
https://stackoverflow.com/questions/8046662/hibernate-opensession-vs-getcurrentsession
https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/transactions.html
https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/architecture-current-session.html
https://docs.jboss.org/hibernate/core/3.3/reference/en/html/architecture.html#architecture-current-session
https://docs.jboss.org/hibernate/core/3.3/reference/en/html/session-configuration.html#configuration-j2ee-currentsession
OpenSession
Return a new session object on every call
- We can use this method when we decided to manage the Session our self.
- It does not try to store or pull the session from the current context.
- If we use this method, we need to flush() and close() the session. It does not flush and close() automatically.
Transaction transaction = null; |
currentSession
creates a brand new session if one does not exist or uses an existing one if one already exists. It automatically configured with both auto-flush and auto-close attributes as true means Session will be automatically flushed and closed.
The "current session" refers to a Hibernate Session bound by Hibernate behind the scenes, to the transaction scope.
Values for the current_session_context_class will be,
- thread(local transaction)
- managed
- jta(global transaction)
1. thread - session bound to a thread, for single thread execution if you call a getCurrentSession() then it will return you a same session object.
2. managed - this provided for managing session from some external entity, something like intercepter. maintaining session in a ThreadLocal same as a "thread" type, but having a different methods like bind(), unbind(), hasbind() to be used by external entity to maintain session in a context.
3. jta - session will be bound to a transaction, as we says a transaction then we need application server for using this context class.
通常建议session per request or per trx
https://docs.jboss.org/hibernate/core/3.3/reference/en/html/architecture.html#architecture-current-session
Contextual Session
Starting with version 3.0.1, Hibernate added the SessionFactory.getCurrentSession()
method. Initially, this assumed usage of JTA
transactions, where the JTA
transaction defined both the scope and context of a current session. However, as of version 3.1, the processing behind SessionFactory.getCurrentSession()
is now pluggable. To that end, a new extension interface, org.hibernate.context.CurrentSessionContext
, and a new configuration parameter, hibernate.current_session_context_class
, have been added to allow pluggability of the scope and context of defining current sessions.
-
org.hibernate.context.JTASessionContext
: current sessions are tracked and scoped by aJTA
transaction. The processing here is exactly the same as in the older JTA-only approach. See the Javadocs for details.
-
org.hibernate.context.ThreadLocalSessionContext
:current sessions are tracked by thread of execution. See the Javadocs for details.
-
org.hibernate.context.ManagedSessionContext
: current sessions are tracked by thread of execution. However, you are responsible to bind and unbind aSession
instance with static methods on this class: it does not open, flush, or close aSession
.
The most common pattern in a multi-user client/server application is session-per-request. In this model, a request from the client is sent to the server (where the Hibernate persistence layer runs), a new Hibernate Session
is opened, and all database operations are executed in this unit of work. Once the work has been completed (and the response for the client has been prepared), the session is flushed and closed. You would also use a single database transaction to serve the clients request, starting and committing it when you open and close the Session
. The relationship between the two is one-to-one and this model is a perfect fit for many applications.
The challenge lies in the implementation. Hibernate provides built-in management of the "current session" to simplify this pattern. All you have to do is start a transaction when a server request has to be processed, and end the transaction before the response is sent to the client. You can do this in any way you like, common solutions are ServletFilter
, AOP interceptor with a pointcut on the service methods, or a proxy/interception container. An EJB container is a standardized way to implement cross-cutting aspects such as transaction demarcation on EJB session beans, declaratively with CMT. If you decide to use programmatic transaction demarcation, prefer the Hibernate Transaction
API shown later in this chapter, for ease of use and code portability.
Your application code can access a "current session" to process the request by simply calling sessionFactory.getCurrentSession()
anywhere and as often as needed. You will always get a Session
scoped to the current database transaction. This has to be configured for either resource-local or JTA environments, see Section 2.5, “Contextual Sessions”.
Sometimes it is convenient to extend the scope of a Session
and database transaction until the "view has been rendered". This is especially useful in servlet applications that utilize a separate rendering phase after the request has been processed. Extending the database transaction until view rendering is complete is easy to do if you implement your own interceptor. However, it is not easily doable if you rely on EJBs with container-managed transactions, as a transaction will be completed when an EJB method returns, before rendering of any view can start. See the Hibernate website and forum for tips and examples around this Open Session in View pattern.