This is a very common conundrum, and a question many people struggle with.
The most common response from people much better looking than me is to use the Open Session in View strategy, which bacically means you allow your client to open the session and demarcate the transaction, leaving the session open even during the view phase, and thus eliminating the chance of any LazyInitializationException from happening.
Here's a little tutorial from Hibernate.org that discusses the topic:
Here's a Spring/Hibernate tutorial that might be useful - it includes complete configuration files and code. It shows how to use control transactions (from the web tier in this example) and uses annotations on the DAO classes for Spring Transactions.
Thanks Andy abd Jao, They both are good sources to read. Can you please suggest me in which situation we should use hibernate.current_session_context_class configuration strategy as thread and managed. As we have to pick one if I am not wrong.
Thanks Andy and Joao, They both are good sources to read. Can you please suggest me in which situation we should use hibernate.current_session_context_class configuration strategy as thread and managed. As we have to pick one if I am not wrong.
Always try to separate transaction demarcation code from you business logic. Never execute transaction code with the code that run queries or make some business logic decisions.
First implement some TransactionOrchestrator that does the following
Execute method of one of you business class that implement a common interface. For example MyProgramInterface.execute(DomainObject object)
Close transaction if success
Rollback transaction if failure.
It gives you a flexibility to write transaction code only once. You can have million of beans that use ORCHESTRATOR_BEAN as their parent. Only what they need to replace is a reference to implementation of MyProgramInterface.
You program interface does not care if it runs in transaction or not. Or how transaction was opened. Only thing it needs to do in case of failure is throw an exception to let your ORCHESTRATOR_BEAN that it needs to rollback a transaction
Generally we will open the session the Hibernate Session in DAO layer. Because when you finish storing/retrieving the records it will be easy to close the session in DAO.
if you have opened the session in service layer or other layer and you store/try to retrive the code and you got some exception with your business logic the session will not be closed because of that error/exception. so the connection will not be closed until and unless you are closing the connections in service or other layer later.
I always feel it is best to handle transactions from the service (business) layer.
The reason for this is simple. It is likely that a single business operation will need to call multiple DAO methods. This operation will be a single unit of work (i.e. a transaction). If one of the invoked DAO methods throws an exception, the entire transaction can be rolled back in the service layer which catches the exception. This cannot be achieved if you start and end a transaction for each DAO method.
Defining a start of any transaction depends on Application Architecture. One can not say start point of Transaction at any layer. We believe that, Architecture very well aware of boundary of any transaction exists in Application.
First of all, the way you approach session and transaction using HibernateUtil is kinda old school. Since you are using Spring framework, you should let spring handle the session and transaction using spring annotation.
To answer your question,
It is true that you can open session and transaction in any layer of your application, but since you are asking for the best place where to open session/transaction, then the answer is
hibernate sessions is best place in DAO layer, while hibernate Transactions is best place in the service layer.
First let make clear.
There are two concepts
OLD WAY: Bound hibernate session to thread. One thread - one session.
NEW WAY. Bound hibernate session to transaction. One transaction - one hibernate session.
If you chose the old way - you are on your own, not gonna advice anything but most common approach create a transaction the same place thread get connected first time to your code (Servlet, StrutsAction, SpringController, WebService Endpoint - plenty of choices but all driven by a controller framework)
If you chose a new way then you are going to use AOP. You will tell to which classes and methods transactions have to be created. Here I give you few advices
1. Start from defining interfaces. AOP only works with interfaces so if you have a class/method reference that a new transaction should start - not gonna work. Use only interface references.
2. Every DAO method should be able to start transaction by using transaction demarcation (REQUIRED/SUPPORT). You need it for unit testing. Never (Never !) in production transaction shell be started by
direct call to DAO but for running unit tests you have to keep a gate open. So ideally you will have two configurations one for prod, another one for unit testing
3. For every transaction as people above say you have to define an orchestrator. For me it is just a dummy Spring bean that has million of definitions - each invokes a program that implements the same interface.
Pointcut saying my orchestrators need a transaction
And I have a million of beans based on the same orchestrator class
Orchestrator here is just a class that invokes a program that might need a transaction. It validates a form, convert form parameters into domain object and passes them to program that has to handle a request. Spring AOP makes sure that transaction is created and commited/rolled back once orchestration is completed
I have used spring+hibernate in several swing applications and the approach is pretty much the same than web applications. Open the sessions at DAO level and set the transactions at service layer. The UI is implemented by panels and forms and you should use the service layer to access data and to implement your business logic.
One useful question is what would happen if you have to change your Application from Swing to Web (or vice versa). The answer should be "just change the UI". Keep that in mind and your architecture will be fine.