This question already has answers here:
Hibernate Performance Best Practice?
(3 answers)
Closed 7 years ago.
I am facing some performace issue in my application. Especially while saving to and retrieving from the database.
My application is a standalone application. Not a webapplication. I am using hibernate for database communication.
This application has not gone in production. This application will be used 50 people simultaneously.
Here is the below code which I have used for getting session. I suspect below is the code for getting slowness.
public class HibernateUtil {
public Session getSession() {
SessionFactory buildSessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = buildSessionFactory.openSession();
return session;
}
public Transaction getTransaction() {
return getSession().getTransaction();
}
}
I am not sure how to write a good code for opening session.
Can anyone suggest how to refactor this code to a good code?
Also, are the session getting closed, means once the thread has completed a process, are we closing the session.
There is no single statement answer for your question unless the code is observed, there are lot of attributes on which the performance of the system depends.
1.) GC - When and which algorithm being used.
2.) How many session are getting opened, are there any sessions which are left idle. Long running sessions should be avoided.
3.) Introducing Caching mechanism in the code, Hibernate 2nd Level cache, query caching
4.) How big the objects are getting retrieved from the database.
5.) How many queries are getting fired into DB.
Please refer this, this
I faced the similar type of issue in past, the base culprit for this is your are creating the factory instance every time when you are trying to get a transaction.
Please use the singleton pattern to create the SessionFactory object, means just create Session factory once and get all the session instance from that factory object, I am pretty sure you will not face the performance issue after this change
change Something like below-
static SessionFactory buildSessionFactory;
public static getSessionFactory() {
if(buildSessionFactory==null) {
buildSessionFactory = new
AnnotationConfiguration().configure().buildSessionFactory();
}
}
public Session getSession() {
getSessionFactory();
Session session = buildSessionFactory.openSession();
return session;
}
public Transaction getTransaction() {
return getSession().getTransaction();
}
It will solve your problem
Related
I am trying to develop a forum system as a part of a university assignment,
which contains a database connectivity part.
I am writing the server in java and decided to use hibernate as an ORM tool to save and load from the data base.
My question is not about the syntax, but about the design of the entire system regarding the database.
Who should be in charge of creating a session and commit transactions? should I make a singleton which recive an object and save it to the database and use this singelton in every setter/constructor of the different classes?
should each change in a memory object be commited directly or should I commit only every few changes? (and if so what is the best way to do this?)
Ideally, a framework should do that for you. Using Spring, for example, you could simply mark methods of Spring beans transactional using an annotation, and the session and transaction handling would be done by Spring:
#Autowired
private SessionFactory sessionFactory;
#Transactional
public void foo() {
Session session = sessionFactory.getCurrentSession();
// do some work with the session
}
instead of
private SessionFactory sessionFactory;
public void foo() {
Session sess = sessionFactory.openSession();
Transaction tx = null;
try {
tx = sess.beginTransaction();
// do some with the session
tx.commit();
}
catch (RuntimeException e) {
if (tx != null) {
tx.rollback();
}
throw e;
}
finally {
sess.close();
}
}
You should neither commit after each change, nor commit every few changes. You should commit atomic, coherent changes. That's the whole point of transactions:being able to go from a coherent state of your database to another coherent state of your database.
For example If posting a message to a topic forum consists in
persisting a message instance
incrementing the messageCount field of the forum
creating a notification for the topic poster
then these three changes should be in a single transaction, to make sure you don't end up with the message being persisted, but the messageCount not being incremented.
I suggest you leave creating and committing transactions to the container, unless you are sure you want to do it yourself. In this case you can use JTA, and use Container Managed Transactions (CMT). Also remember to avoid entitymanager-per-operation antipattern. To learn more read about Transactions and Concurrency and decide yourself what suit you the best.
Take a look at the DAO (Data Access Object) pattern. It will help to provide a pattern which will help you to encapsulate your data access.
http://en.wikipedia.org/wiki/Data_access_object
Also, this page does a great job:
Data access object (DAO) in Java
As for the second question, the answer entirely depends on your requirements. Usually you want to commit at least once per user interaction. That might be the result of several in-memory changes. It is definitely easier to commit after each entity is changed.
I am learning Hibernate now and I need help to understand how Sessions work. I have some methods in a class which I have given below.
I see there is a getCurrentSession() in SessionFactory class. So, it seems that only one Session can be "active" inside a SessionFactory. Is this SessionFactory like
a queue of transactions where the transactions are completed in in order ? If yes, then
is it possible to promote a transaction to a higher or lower priority ?
private static SessionFactory factory;
//Get a hibernate session.
public static Session getSession(){
if(factory == null){
Configuration config = HibernateUtil.getConfiguration();
factory = config.buildSessionFactory();
}
Session hibernateSession = factory.getCurrentSession();
return hibernateSession;
}
public static void commitTransaction(){
HibernateUtil.getSession().getTransaction().commit();
}
public static void rollbackTransaction(){
HibernateUtil.getSession().getTransaction().rollback();
}
And some more methods that use getTransaction().
SessionFactory's job is to hide the session creation strategy. For example, in a web application, you probably want the SessionFactory to return create a Session the first time getCurrentSession() is called on a thread, and then return the same Session from that point forward for the duration of the request. (Since you probably want to load customer data from that session, then maybe modify their account in that same session.) Other times, you may want SessionFactory to create a brand new session every time you call getCurrentSession(). So by hiding this decision behind the SessionFactory API, you simply write code that gets the Session from the factory and operates on it.
The Session is what handles transactions. As you probably expect, transactions are started in a Session, and then either complete or rollback. There is really no way to prioritize them since once they are started, you are committed to either rolling it back or committing it.
This question already has answers here:
Why is HibernateDaoSupport not recommended?
(2 answers)
Closed 9 years ago.
I was used to getHibernateTemplate() in hibernate 3, and now I am moving to Hibernate 4 for and here I didn't find following class:
org.springframework.orm.hibernate4.support.HibernateDaoSupport;
And here I had read about it is not more recommended to use
http://forum.springsource.org/showthread.php?117227-Missing-Hibernate-Classes-Interfaces-in-spring-orm-3.1.0.RC1
Can someone explain me why? and in hibernate 4 will now I need to do all task like commiting, close, flushing the transaction which was automatically managed by getHibernateTemplate() method?
Because its main goal was to get a Hibernate session tied to the current Spring transaction, when SessionFactory.getCurrentSession() didn't exist. Since it now exists (and for a long time: HibenateTemplate usage is discouraged even in the hibernate3 package), there is no reason to use this Spring-specific class instead of using SessionFactory.getCurrentSession() to get a session tied to the current Spring transaction.
If you use Spring, then you should use its declarative transaction management, which allows you to avoid opening, committing, closing and flushing. It's all done by Spring automatically:
#Autowired
private SessionFactory sessionFactory;
#Transactional
public void someMethod() {
// get the session for the current transaction:
Session session = sessionFactory.getCurrentSession();
// do things with the session (queries, merges, persists, etc.)
}
In the above example, a transaction will be started (if not already started) before the method invocation; A session will be created by Spring for the transaction, and the session will be automatically flushed before the commit of the transaction, that will be done by Spring automatically when the method returns.
I'm using Spring to manage transaction in my service layer with #Transactional annotation.
This is fine for eager loaded collection, but is bad for lazy loading.
I cant use OSV pattern, my application is a standalone desktop client application.
So I thought about a solution, and this is what I tried to do:
public abstract class TransactionTask {
public TransactionTask() {
}
public abstract void job();
}
In my service I have:
#Transactional
public void doJob(Transactiontask tt){
tt.job();
}
And how I use it is:
myService.doJob(new TransactionTask() {
#Override
public void job() {
//lazy code here
}
});
I expect to see this code work, becouse session is open in doJob method(it is marked as transactional), but it doesn't work...the exception is no session or session was closed.
Why this code doesn't work, and how can I load a collection only when i need it?
I do not want to write a service with a specified method to load collection, that is not a solution.
Lazy Loading doesn't require just a session, it requires the session that your Entity is attached to. You need to attach the objects to the new session created by #Transactional before you try to access the lazy fields.
Also, while you obviously cannot use one of the available OSIV servlet filters, the 'pattern' is still valid. There has to be some definable scope that you can couple the lifecycle of a session to. (It may prove to be so large that there are other challenges making it not worth the effort, but it is still an option.)
E.g. you have User user object. It's detached that's why you got "the exception is no session or session was closed".
You can reread it from the dao user=userDao.findById(user.getId()) and then get lazy collections of the newly retrieved object.
I run following working code:
Session session = null;
try {
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();
session = sessionFactory.openSession();
String id = (String) FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap().get(
"storeId");
Transaction t = session.beginTransaction();
stores = getStores();
for (Store store : stores) {
if (store.getId() == Integer.parseInt(id)) {
session.delete(store);
}
}
t.commit();
} catch (Exception e) {
} finally {
session.close();
}
}
When i try redo this code to use Hibernate template, i go unending request to DB:
HibernateTemplate template = new HibernateTemplate();
template .setSessionFactory(sessionFactory);
stores = template.find("from Stores");
for (Store store : stores) {
if (store.getId() == Integer.parseInt(id)) {
template.delete(store);
}}
Looks like transaction is not closed.
How could I close transaction this case? And is it will better at all to use Hibernate template approach instead of session approach showed at first code?
You didn't say it, but I assume you're referring to the HibernateTemplate class in the Spring Framework. HibernateTemplate participates in Spring transactions, but it doesn't manage them on its own. Spring provides a lot of ways to manage transactions both programmatically and declaratively. If you're just experimenting, you can use the TransactionTemplate class to quickly test it out. For larger projects, you should consider using declarative transaction management because it simplifies your code, although it's a little trickier to set up initially.
As for whether or not the HibernateTemplate approach is better than managing your sessions manually, I'd say anything that reduces boilerplate code is a good thing, so yes. This is especially crucial on big projects. However, depending on your project, HibernateTemplate might not even be necessary. It was originally created to work around some deficiencies in Hibernate 2.x, but many of those deficiencies were eliminated in Hibernate 3. So before adopting it, read the HibernateTemplate JavaDoc for a discussion of the advantages.