Best way to get Session and Release session in HIbernate/SQL - java

Consider the below two codes.
Session session = null;
query = "update Employee set EMPLOYEE_NAME = 'Jay' where EMPLOYEE_ID = 1";
try {
session = getSession();
Query query = session.createSQLQuery(dlquery);
query.executeUpdate();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if(session != null) {
releaseSession(session);
}
}
And....
Session session = getSession();
query = "update Employee set EMPLOYEE_NAME = 'Jay' where EMPLOYEE_ID = 1";
try {
Query query = session.createSQLQuery(dlquery);
query.executeUpdate();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if(session != null) {
releaseSession(session);
}
}
Which among the two is better to use? Or is there a better way? What wrong I might be doing here?
Also should we do a null check before calling releaseSession(session) in finally?

Truly, the best way is to leverage Spring and its JPA/Hibernate support.... You'll never have to deal with it in your code.

To be honest, I'd say there wasn't much difference at all in the two, but you should always check if the session is null, just so you don't cause another NullReferenceException.
Unfortunately this is probably the cleanest way to do this in Java, as there is no such thing as the "using" statement as there is in C#, which allows you to dispose the object after the using block has finished executing.

I would suggest using a transaction. If tomorrow you change your code to add another update for instance, you won't have to worry about any consistency problem in case something happens while executing an update. Aside from that, I would suggest using parameters in your query rather than hard-coding the values. This way you could reuse the query.

If getSession() throws an Exception for some reason, would not it be problem in second solution?

Use the below syntax to get and release session.
session = getSession();
Query query = session.createSQLQuery(dlquery);
query.executeUpdate();
session.close();

Related

Hibernate not getting changes from database even I turn off the session everytime and turn off the 2nd level cache

I have a hibernate fetch as follows (it is called by a synchronized method in threads). The problem is if I updated the status_id to 1 in the DB console, the code won't pick it up. And when I run the sql Hibernate show_sql printed out in the console, it can find one record. Moreover, I can see the select sql being run every time via show sql.
To make the problem clear, if I update the record status to 1 and then start the application, the code will return me one record and after processing, the record status will be updated to 2. As I expected, after that, the code will return nothing cause the status being updated to 2. However, if I manually update the status to 1, it won't pick it up.
As you can see from the configuration, I have already turn off the 2nd level cache and every time, I close the session. I am using Enum to define the Hibernate connection. So the sessionFactory is always the same instance. I don't know if this matters but I assume that is what it should be.
The dao code is
Session session = null;
String sql = "from MyEntity rr where status_id = 1;"
try {
session = getSessionFactory().openSession();
Query q = session.createQuery(sql);
q.setMaxResults(1);
List resultList = q.list();
if (resultList.isEmpty())
return null;
return (MyEntity) resultList.get(0);
} catch (Exception e) {
LOGGER.error(e.getMessage());
} finally {
if (session != null) {
session.close();
}
}
return null;
The code to update the status is
Session session = null;
try {
session = getSessionFactory().openSession();
session.beginTransaction();
session.update(myEntity);
session.flush();
session.getTransaction().commit();
} catch (Exception e) {
LOGGER.error(e.getMessage());
} finally {
if (session != null) {
session.close();
}
}
If the entity doesn't exist, you need to invoke save() on it, otherwise you need to invoke update(), it will modify the existing persistent object in database.
Be aware everytime invoke save() would insert a new row in database. You may use saveOrUpdate() to achieve above save() and update() actions, Hiberate will either call save or update depends on the situation and take care of it.
You can invoke flush() after each saveOrUpdate() which forces Hibernate execute save or update in your database.
I found the solution. Once I put the transaction on fetch, it start to work. Don't know why. Any one can give some explaination? Thanks.

java.lang.OutOfMemoryError with hibernate

I get the below error when I ran the below code. May I know what is wrong in my code. Thanks in advance . I am using hibernate and java
HTTP Status 500 - Handler processing failed; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded
#Autowired
SessionFactory sessionFactory;
Session session = null;
Transaction tx = null;
public String getEntityList(String userIds, String callerID) throws Exception {
session = sessionFactory.openSession();
tx = session.beginTransaction();
List<User> userList = session.createCriteria(User.class)
.list();
//Query the database
CallableStatement stmt = null;
String returnVal = "";
ResultSet rs = null;
try {
stmt = ((Connection) session).prepareCall("{?=call WS_Distributionlist(?,?)}");
} catch (SQLException e) {
e.printStackTrace();
}
try {
// left over accounts processing
stmt.executeUpdate();
returnVal += stmt.getString(1) + "|";
System.out.println("RETURN VALUE in tail end :::::: "
+ returnVal);
//returnVal = returnVal.substring(0, returnVal.length() - 1);
System.out.println("Return Value " + returnVal);
session.close();
//return returnVal;
} catch (SQLException e) {
System.out.println("Error while executing the database function ");
} finally {
session.close();
}
tx.commit();
session.close();
return returnVal;
}
A lot of useful details are missing:
userIds is an input parameter of the function where is it used?
userList, how many users are there and where are they used?
WS_Distributionlist(?,?) has 2 input parameters, where do you set them?
I cannot understand the following line of code:
((Connection) session).prepareCall("{?=call WS_Distributionlist(?,?)}");
I've seen and used many technique to get a connection out of an hibernate session, none of which where casting the session itself to connection, but this is more or less a personal curiosity.
The point is that there is a lot of missing code, so I can just speculate that one of this calls produces an huge dataset, or that you are passing some huge parameter to a statement.
Either way, if you deal with HUGE dataset you should probably use a StatelessSession , because stateless session have nearly zero memory overhead (no caching).
If you build your own statement from connection , use FORWARD_ONLY_CURSOR.
Try setting the fetchSize on the statements that returns resultset.
Consider using either a ScrollableResult or an Iterator instead of a List as a result.

Hibernate for simple query

I am a newbie in hibernate and started working on it . I am trying to use hibernate for one of my project which contains a simple Login page .
Someone (senior) told me why to use hibernate for such a simple query, it will have a performance issue and I should use simple JDBC for that page.
Can anyone advice me for what type of queries I can use in hibernate ?
Thanks
The question of performance is everywhere and not unique to hibernate so it all depends on how you structure your Project because even in JDBC for example there is a strong argument of using PreparedStatement in place of Statement. In Hibernate you can use HSQL or opt for the more cool Criteria API. I actually prefer the Criteria API because I do not have to write any query, I leave that to the Hibernate engine.
So assuming you have a table called Users in your database and it contains the username and password for login in users, a simple boolean method like this will serve you very well and as you can notice, you will not need to write any query. This actually makes your application more independent in regards to databases because it works with most databases with minimal changes.
public static boolean userExists(String userName, String userPassword) {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
long count = 0;
try {
tx = session.beginTransaction();
Criteria cr = session.createCriteria(Users.class);//Users.class is the mapping class for your database Objects.
cr.add(Restrictions.eq("userName", userName));
cr.add(Restrictions.eq("userPassword", userPassword));
count = (Long) cr.setProjection(Projections.rowCount()).uniqueResult();
tx.commit();
} catch (Exception asd) {
System.out.println(asd.getMessage());
if (tx != null) {
tx.rollback();
}
} finally {
session.close();
}
return count > 0;
}
So when you pass username and password parameters if a user and password matches, the boolean will return true otherwise it will return false.
In the background the engine will generate this query:
select count(*) from Users where user_name = ? and user_password = ?
There is a nice tutorial here where you can refer.

Hibernate's Criteria query makes Tomcat become not responive after a few request services

I am running a Spring + Hibernate web application on Tomcat 7.0.35 (Spring 3.1, Hibernate 3.6.1, JPA 2.0).
This app has a page that gets data from the database via Hibernate's Criteria (I know I dont have to). The service tier simply calls the data tier. Here is the code:
Criteria criteria = sessionFactory.openSession().createCriteria(Article.class);
criteria.addOrder(Order.desc("updatedTime"));
criteria.add(Restrictions.eq("account", acc));
criteria.add(Restrictions.eq("draft", true));
criteria.setMaxResults(1);
Article s = (Article) criteria.uniqueResult();
return s;
Tomcat can only serve a few requests from this page, and then it becomes non-responsive. I can see the browser keeps waiting for server response (Firefox status bar shows "waiting for host".)
I am not seeing any error message such as OutOfMemory, etc. It appears that the browser waits forever.
If I change it to JPA as follows:
#NamedQuery(name = "Article.getMostRecentDraftArticle", query = "select x from Article x where x.account = :account and x.draft = 1 order by x.updatedTime desc"),
.....
Query q = getSession().getNamedQuery("Article.getMostRecentDraftArticle");
q.setParameter("account", acc);
q.setMaxResults(1);
List list = q.list();
if (list.size() == 0)
return null;
else
return (Article) list.get(0);
Then everything works right.
What could go wrong with my use of Hibernate's Criteria API?
Thanks for any input!
Cheers.
You haven't closed the session. See this answer: https://stackoverflow.com/a/4049758/116509
and read the javadoc of org.hibernate.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();
}
Can you see the hibernate logs? does it generate the query?
Anyway, you can try to put a sessionFactory.getCurrentSession().flush(); below Article s = (Article) criteria.uniqueResult();

javax.persistence.NoResultException: getSingleResult() did not retrieve any entities

i have created a namedquery with ejb to check if the username is used.
When the singleResult is null, then i get the following Exception :
javax.persistence.NoResultException: getSingleResult() did not retrieve any entities
But this exception is the result that i want when the username is free.
Here is the code:
public User getUserByUsername(String username) throws DAOException{
try{
Query q = em.createNamedQuery(User.getUserByUsername);
q.setParameter("username", username);
return (User) q.getSingleResult();
}catch(Exception e){
throwException(username, e);
return null;
}
}
Does anybody know what the problem is. :(
I would like to return null and don`t get an Exception.
Thank you very much
You seem to rethrow the exception in your catch block with the statement throwException(username, e);. If you expect to get the user or null without any exception this should look like the following:
public User getUserByUsernameOrNull(String username) {
try{
Query q = em.createNamedQuery(User.getUserByUsername);
q.setParameter("username", username);
return (User) q.getSingleResult();
} catch(NoResultException e) {
return null;
}
}
Use getResultList instead and check if the List is empty (has zero element). Otherwise, the list contains one element and you simply return it.
You experience the defined behaviour when calling getSingleResult and none entry was found: A NoResultException is thrown. You can catch NoResultException in the catch-clause, because the transaction won't be marked as rollback, when JPA is throwing NoResultException. Or you can use getResultList() and check if size is exactly "1", so you know you have found your user.
Additionally, I wouldn't return "[null]" if the user is not found, but throw a checked UserNotFoundException (to be defined). But this depends on the contract of the method you are going to implement.
Michael said: "You can catch NoResultException in the catch-clause, because the transaction won't be marked as rollback, when JPA is throwing NoResultException.". It looks like for some jpa implementations, the NoResultException will rollbak transaction, which violates jpa specification, according to this article: NoResultException marks transaction rollback
If your application uses Spring Roo the most voted answer doesn't work: the exception is caught by the aspects and you never get the desired NoResultException.
The only way to solve the issue is to use getResultList and to check for zero, one or more results in the resulting List, as stated in the second most voted answer.
try {
Query queryObj = entityMgrObj
.createQuery("SELECT u FROM UserEntity u WHERE u.email = :email AND u.password = :password");
queryObj.setParameter("email", email);
queryObj.setParameter("password", password);
UserEntity userEntity = (UserEntity) queryObj.getSingleResult();
return userEntity;
} catch (NoResultException e) {
return null;
}
What does the method throwException do?
Is an exception being thrown within it but you are using the prior exception's message?
Catch NoResultException in try-catch block and handle it as per your requirement such as returning a null value.
Example of try-catch is detailed in the following link:
http://www.javabrahman.com/j2ee/jpa/no-result-exception/

Categories