hibernate SessionFactory

hibernate SessionFactory

Session

A typical transaction should use the following idiom:

Session sess = factory.openSession();
Transaction tx;
try {
tx = sess.beginTransaction();
//do some work
...
tx.commit();
}
catch (Exception e) {
if (tx!=null) tx.rollback();
throw e;
}
finally {
sess.close();
}

Session load vs get

  1. get() loads the data as soon as it’s called whereas load() returns a proxy object and loads data only when it’s actually required, so load() is better because it support lazy loading.
  2. Since load() throws exception when data is not found, we should use it only when we know data exists.
  3. 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;
Session session = HibernateUtil.getSessionFactory().openSession();
try {
transaction = session.beginTransaction();
// do Some work

session.flush(); // extra work
transaction.commit();
} catch(Exception ex) {
if(transaction != null) {
transaction.rollback();
}
ex.printStackTrace();
} finally {
if(session != null) {
session.close(); // extra work
}
}

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,

  1. thread(local transaction)
  2. managed
  3. 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 a JTA 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 a Session instance with static methods on this class: it does not open, flush, or close a Session.

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.