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.
Related
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.
I've seen a bunch of links about changing the credentials that hibernate uses to connect to a database, but nothing about whether or not you can use hibernate to execute something like SET PASSWORD FOR 'username'= PASSWORD('password'). I'd also like to be able to grand users privileges, display all the databases and create new users as well. Basically can I do anything other than table operations with Hibernate?
For example I've tried the following to create a user:
SessionFactory factory = new Configuration.configuration().buildSessionFactory();
Session session = factory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
String query = "CREATE USER 'testUser' IDENTIFIED BY 'password'";
SQLQuery query = session.createSQLQuery(query);
tx.commit();
}catch(HibernateException e){
if(tx != null){
tx.rollback();
}
e.printStackTrace();
}finally{
session.close();
}
factory.close();
I know it runs everything correctly, but no user is created.
You need to call executeUpdate() on your SQLQuery instance - query.executeUpdate() - this will issue your CREATE USER statement to the database. Currently you're creating the query instance and doing nothing with it.
we are using hibernate to Insert/Update/Delete data in mysql db.
whenever the hibernate query is fired it is shown on console.
But my requirement is to store the query in db for audit purpose. hence i would require to store the query in a string variable so that i can further save it in db.
public int updatebarePumpData(Tbl13BarePumpData barePumpData)
{
if (log.isInfoEnabled())
log.info("start--BarePumpGADaoImpl---updatebarePumpData");
int ans = 0;
session = HibernateUtil.getSessionFactory().getCurrentSession();
try
{
tx = session.beginTransaction();
Tbl13BarePumpData barepumpObj = (Tbl13BarePumpData) session.load(Tbl13BarePumpData.class, barePumpData.getBarePumpdataId());
barepumpObj.getBarePumpdataId();
barepumpObj.setParameter(barePumpData.getParameter());
barepumpObj.setValue(barePumpData.getValue());
barepumpObj.setModifiedBy(barePumpData.getModifiedBy());
barepumpObj.setModifiedDate(barePumpData.getModifiedDate());
session.save(barepumpObj);
tx.commit();
ans = barepumpObj.getBarePumpdataId();
}
catch (Exception e)
{
if (tx != null && tx.isActive())
tx.rollback();
log.error(e.getMessage(), e);
}
if (log.isInfoEnabled())
log.info("end--BarePumpGADaoImpl---updatebarePumpData");
return ans;
}
The console output is
Hibernate: update pumpManagement_mp.dbo.tbl_13_barePump_data set barepumpga_id=?, parameter=?, value=?, createdBy=?, createdDate=?, modifiedBy=?, modifiedDate=?, company=? where barePumpdata_id=?
I would like to have the same Output in a variable
String qry=hibernate show query
Any help would be appreciated
Thanks & Regards,
Pranav C Lunavat
Following code help you how to get sql query of Criteria.
Criteria criteria = session.createCriteria(User.class);
CriteriaImpl c = (CriteriaImpl)criteria;
SessionImpl s = (SessionImpl)c.getSession();
SessionFactoryImplementor factory = (SessionFactoryImplementor)s.getSessionFactory();
String[] implementors = factory.getImplementors( c.getEntityOrClassName() );
CriteriaLoader loader = new CriteriaLoader((OuterJoinLoadable)factory.getEntityPersister(implementors[0]),
factory, c, implementors[0], s.getEnabledFilters());
Field f = OuterJoinLoader.class.getDeclaredField("sql");
f.setAccessible(true);
String sql = (String)f.get(loader);
I hope this will help you.
There is this way of using a JDBCAppender of log4j, and then use log4j configuration as below. How much of unwanted logs, because of the nature of Hibernate, is something which you will have to try and find out.
Log4j DB Logging
Something like this will be your final configuration.
log4j.rootLogger = DEBUG, DB
log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DB.URL=jdbc:mysql://localhost/DBNAME
log4j.appender.DB.driver=com.mysql.jdbc.Driver
log4j.appender.DB.user=user_name log4j.appender.DB.password=password
log4j.appender.DB.sql=INSERT INTO LOGS VALUES('%x','%d','%C','%p','%m')
log4j.appender.DB.layout=org.apache.log4j.PatternLayout
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();
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();