Hibernate Session Factory - java

In our web application we have a HibernateSessionFactory class, that is opening and closing connections. Everything is okay, but when we are updating data in the database, it doesn't change in our application. Unfortunately, we see old data from the database. How can I fix it?
public class HibernateSessionFactory {
private static final ThreadLocal threadLocal = new ThreadLocal();
private static org.hibernate.SessionFactory sessionFactory;
private static Configuration configuration = new Configuration();
private static ServiceRegistry serviceRegistry;
private static final Logger log = Logger.getLogger(HibernateSessionFactory.class);
static {
try {
configuration.configure();
serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
. buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
log.error("Error Creating SessionFactory",e);
}
}
private HibernateSessionFactory() {
}
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}
return session;
}
public static void rebuildSessionFactory() {
try {
configuration.configure();
serviceRegistry = new ServiceRegistryBuilder(). applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
log.error("Error Creating SessionFactory",e);
}
}
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.flush();
session.close();
}
}
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Configuration getConfiguration() {
return configuration;
}
}

Hibernate is a sofisticated and complex framework for building a layer between your program and the database, providing an object oriented model to help object oriented programs in their job.
In order to do this, and to be more performat of course, it creates a cache which stores somehow some of the data coming from the database, or going to the database.
I think that this problem is NOT concerning the connection to the database but rather how you save and retrive data.
I'll try to explain my self better: when you query database to save data you do the following steps:
open session
open transaction
build object
flush and save object in session
commit transaction
close transaction
close session
eg
public Boolean saveNewCliente(Cliente c) {
Session s = getSession();
Transaction t = null;
try {
t = s.beginTransaction();
s.save(c);
s.flush();
t.commit();
s.close();
return true;
} catch (Exception e) {
if (t!=null) t.rollback();
System.out.println(e.getMessage());
return false;
}
finally{
s.close();
}
}
A common pitfall happens when you query database to fetch data, is to leave the part relating the transaction out of your "query" steps. As well for saving data you have to
open session
open transaction
build query / criteria
execute query over session
close transaction
close session
If you don't follow this steps is possible that you have stale data in your application, but not in your database. A check may be to execute your update/save-query and check manually in the database if the data has changed/created. If your application then loads stale data you know you do the fetch-query in the wrong way(without using transaction).
Here's a snipped of example
public Cliente get(Integer id) {
Session s = getSession();
Transaction tx = s.beginTransaction();
try {
System.out.println("get cliente by id");
Cliente res = new Cliente();
res = (Cliente) s.get(Cliente.class, id);
tx.commit();
return res;
} catch (Exception e) {
tx.rollback();
System.out.println(e.getMessage());
return null;
}finally{
s.close();
}
}
If you want to furthermore investigate you can suspend the usage of cache by hibernate, you can do it in the following way, but remember that if data is cached there is a reason ;)
This can be useful as a quick test in order to proceed in discovering if the error is due to wrong query usage.
You should add this to your hibernate config xml
<!-- to disable cache -->
<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="hibernate.cache.use_query_cache">false</property>

Related

Transactional not able to resolve transaction boundaries - Hibernate

I am trying to do a simple saveOrUpdate operation using a Transaction Manager in Hibernate but, the context is not flushed to the DB tables. I suspect, the Transaction Manager is not able to resolve the end of the transaction and hence, doesn't flush the changes.
The changes are reflected in the DB Table if a session.flush() is done explicitly. I am using the Default flush mode, which is AUTO.
There are a couple of other questions on SO that talk about the same, but none of them have helped in my case.
#Transactional(transactionManager="txManager", readOnly=false)
public Integer setNamesTable(Names names) {
session = getSession();
Integer id = null;
if (session != null) {
try {
id = (Integer) session.save(names);
} catch (Exception ex) {
System.out.println(ex);
}
LOGGER.info("Exiting setNmlAggrTcaPhn");
}
return id;
}
Have Autowired SessionFactory as below,
#Autowired
#Qualifier("hibernateTestAnnotatedSessionFactory")
SessionFactory sfc;
private synchronized Session getSession() {
try {
session = sf.getCurrentSession();
if (session != null) {
return session;
} else {
session = sf.openSession();
}
} catch (HibernateException ex) {
session = sf.openSession();
}
return session;
}

Shorter version of Hibernate query

I have hibernate query, for example get user by id:
public User findById(int id){
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
Transaction tx = null;
User user = null;
try{
tx = session.beginTransaction();
user = (User) session.get(User.class, id);
session.getTransaction().commit();
} catch(HibernateException e){
if(null != tx) tx.rollback();
System.out.println("HibernateException, transaction will be rollbacked");
} catch(Exception e){
e.printStackTrace();
}
finally {
session.close();
}
return user;
}
It's ok for one query, but i need dublicate all of this code to every query.
I need just on single code:
user = (User) session.get(User.class, id);
Is it possible to put other code to another class, method or something else?
Updated
HibernateUtil:
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from hibernate.cfg.xml
return new AnnotationConfiguration().configure()
.buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
It is a good practice to keep one Hibernate utility class which will have a static method to provide us the hibernate session. Moreover you can reuse the hibernate session by preventing making a new session on each query by using some simple logic.

Proper use of session(hibernate)

Sorry for my english. I learn JavaEE and i dont know proper or not i use session in hibernate. How to use them? I use pattern DAO and hibernate. Tell my how property use session
this is HibernateUtil class
private static final SessionFactory sessionFactory;
static {
try{
sessionFactory = new Configuration().configure("/app/web/landingpage/HibernateConnect/hibernate.cfg.xml").buildSessionFactory();
}catch(Throwable ex) {
System.out.println("Error " + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static void close(Session session) {
if (session != null) {
try {
session.close();
} catch (HibernateException ignored) {
System.out.print("Couldn't close Session" + ignored);
}
}
}
And that class makes all operation db CategoryDaoImpl
public class CategoryDaoImpl implements CategoryDao{
private Session session = null;
//get all category
public Collection getAllCategory() {
List categoris = new ArrayList<Category>();
try{
session = HibernateUtil.getSessionFactory().openSession();
categoris = session.createCriteria(Category.class).list();
}catch(Exception e) {
System.out.println("getAllCategory "+ e);
}finally{
if(session != null && session.isOpen())
session.close();
}
return categoris;
}
//get category id
public Category getCategory(int id) {
Category cat = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
cat = (Category) session.load(Category.class, id);
}catch(Exception e) {
System.out.println("getAllCategory "+ e);
}finally{
if(session != null && session.isOpen())
session.close();
}
return cat;
}
//and below few methods that use it the some way session
}
and this servlet take results indexuser
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
try{
Collection allcategory = Factory.getInstance().getCatDAO().getAllCategory();
request.setAttribute("allcategory", allcategory);
request.getRequestDispatcher("/index.jsp").forward(request, response);
} catch(Exception e) {
System.out.println(e);
} finally{
if(session!=null && session.isOpen())
session.close();
}
The main contract here is the creation of Session instances. Usually an application has a single SessionFactory instance and threads servicing client requests obtain Session instances from this factory.
The internal state of a SessionFactory is immutable. Once it is created this internal state is set. This internal state includes all of the metadata about Object/Relational Mapping.
Basically session is used to get physical connection with database. So while you performing any DB Operations it will first open Session using sessionFactory and then Session do physical connection with database and then perform your operation and after performing operation you can close it.
Session is light weight.

HibernateSessionFactory class doesn't change data from database

In our application we have an HibernateSessionFactory class, that is opening and closing connections. Everything is okay, but when we are updating data in the database, it doesn't change in our application. Unfortunately, we see old data from the database. How can I fix this?
public class HibernateSessionFactory {
private static final ThreadLocal threadLocal = new ThreadLocal();
private static org.hibernate.SessionFactory sessionFactory;
private static Configuration configuration = new Configuration();
private static ServiceRegistry serviceRegistry;
private static final Logger log = Logger.getLogger(
HibernateSessionFactory.class);
static {
try {
configuration.configure();
serviceRegistry = new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
log.error("Error Creating SessionFactory", e);
}
}
private HibernateSessionFactory() {}
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ?
sessionFactory.openSession() : null;
threadLocal.set(session);
}
return session;
}
public static void rebuildSessionFactory() {
try {
configuration.configure();
serviceRegistry = new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (Exception e) {
log.error("Error Creating SessionFactory", e);
}
}
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.flush();
session.close();
}
}
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Configuration getConfiguration() {
return configuration;
}
}
.
#SuppressWarnings("unchecked")
public List<Tauthor> getAuthors() throws HibernateException {
log.debug("getting all authors");
Query queryObject = null;
List<Tauthor> authors = null;
Session session = HibernateSessionFactory.getSession();
try {
String queryString = "from Tauthor";
queryObject = session.createQuery(queryString);
authors = queryObject.list();
} catch (HibernateException e) {
log.error("get all authors failed", e);
throw e;
} finally {
HibernateSessionFactory.closeSession();
}
return authors;
}
You haven't shared your code where you write data to the database. Without that, I can think of only a few reasons as to why your data output is old instead of new data:
Your transactions are not being committed.
Hibernate hasn't written to the database at the time of data queried by you.
Hibernate's cache hasn't been updated, which results in query returning old data.
You should verify that data has been written to the Database with a db developer tool and try disabling all hibernate caching to see if the result changes.

Hibernate not closing connection

I am using Hibernate + jersey Rest And Mysql as backend for database. In Hibernate used cp3 pool for connection but after some time it creates so many idle connections and gets stuck. my configurations are :
package com.appname.hibernate.util;
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static SessionFactory sessionFactory;
static {
try {
Configuration configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
} catch (HibernateException he) {
System.err.println("Error creating Session: " + he);
he.printStackTrace();
throw new ExceptionInInitializerError(he);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
////////////////////// INSIDE DAO ///////////////////////////
private Session getSession() {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session;
try {
session = sessionFactory.getCurrentSession();
} catch (org.hibernate.HibernateException he) {
session = sessionFactory.openSession();
}
return session;
}
public Users regsiterUser(Users users) throws Exception {
Session session = null;
try {
session = getSession();
Transaction transaction = session.beginTransaction();
session.saveOrUpdate(users);
transaction.commit();
return users;
//Using context session that is why I am not closing session
} catch (Exception e) { throw e; }
}
I am calling this DAO function form my controller where I am making transaction and session inside DAO layer. Please help me I am trying to solve this but not getting any solution please have a look what is wrong with the above configuration and code ......
Thanks in advance.....
I think this session = sessionFactory.openSession(); should be closed manually after use because it is not managed by an orchestrator that release resource after use.

Categories