-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: Update first level cache
PostPosted: Sat Jun 10, 2006 7:03 pm 
Newbie

Joined: Sun Jun 04, 2006 8:41 pm
Posts: 13
Hello,

how is it possible in a web application to update the first level cache.
Thanks Thomas


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 11, 2006 4:01 pm 
Regular
Regular

Joined: Mon Jun 13, 2005 12:21 pm
Posts: 61
Location: Hannover
Please explain you're scenario. The first level cache is only for a single Session object. It's maintained by hibernate you don't have to update it, unless you're working with triggers or stored procedure. If you, look at Session.evict to get some tips.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 11, 2006 4:49 pm 
Newbie

Joined: Sun Jun 04, 2006 8:41 pm
Posts: 13
Hello, many thank for replying because I have a great problem with hibernate.

I have developed a web application with hibernate 3, struts, common controls and deploy the application to a tomcat server.
Within a browser session I have no problems to update my data. The data is persistent into the database and I can reload the correct data.

If I have two or more browser sessions the other session become no information about the update in the database. I think the stale data is loaded from the session cache. The cache doesn't check for new data.

How can I configure hibernate that other sessions become notice from my updates and load the correct persistent data from the database.

Up to now I'm searching for solution. I use lazy loading and like this feature. I tried also to clear the session. In this case the correct data gets visible for other session, but in this case lazy loading has a problem because of the cleared cache.

Up to now I tried a lot of different way to find a solution (cache etc.) but nothing solves my problem. In the forum there are some other threads with the same problem but without a solution.

Thank a lot if anyone can help me.

Thomas


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 11, 2006 10:10 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 7:19 pm
Posts: 2364
Location: Brisbane, Australia
Sounds like you have some serious threading or application architecture issues.

First thing to do is read this: http://hibernate.org/42.html.
This will provide information about sessions and transactions with a background on various architecture choices available.

Then further questions should include more information on how you are managing transaction boundaies and sessions in your application. That way we can satrt to suggest approaches that might work for you.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 12, 2006 11:40 am 
Newbie

Joined: Tue May 24, 2005 11:25 am
Posts: 16
yallatop wrote:
Hello, many thank for replying because I have a great problem with hibernate.

I have developed a web application with hibernate 3, struts, common controls and deploy the application to a tomcat server.
Within a browser session I have no problems to update my data. The data is persistent into the database and I can reload the correct data. ..
Thomas


If you are using Oracle, take a look on this one. It does not have first-level caching at all.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 12, 2006 2:04 pm 
Newbie

Joined: Sun Jun 04, 2006 8:41 pm
Posts: 13
Hello,
1. No, I didn't use Oracle, I use Mysql as database.
2. The documentation Sessions and transactions are well knows for me.

I try to explain my problem in a little more detail:

I orientated my application to Cave Temptor demo application from the book Hibernate in Action. I use the same generic approach. I have the same GenericHibernateDao as interface to hibernate. Refering to the document 42.html I use a long session approach to work with the user session.
Following you will find my filter class which I include in my web.xml file.

/**
* Project: Lomis-Client
* File name: HIbernateSessionFilter.java
* Package name: com.ebn.lomis.client.filter
* @author Thomas Langhammer
* 02.04.2006 10:10:59
*
*
*/
package com.ebn.lomis.client.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;

import com.ebn.lomis.client.actions.administration.AdministrationMenuAction;
import com.ebn.lomis.client.actions.freiekapazitaeten.FreiKapazitaetfahrzeugAction;
import com.ebn.lomis.common.exceptions.LomisDataAccessException;
import com.ebn.lomis.server.hibernate.util.HibernateUtil;

/**
* Author: Thomas Langhammer
* @hibernate.class table="HIbernateSessionFilter"
*/
public class HibernateSessionFilter implements Filter {

/**
* The logger of the class
*/
private static Logger log=Logger.getLogger(HibernateSessionFilter.class);

private static final String HTTPSESSIONKEY = "HibernateSession";


/**
* Constructor of the class
*/
public HibernateSessionFilter() {
super();
}

/* (non-Javadoc)
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/
public void init(FilterConfig arg0) throws ServletException {
log.info("Servlet filter init, now disconnecting/reconnecting a Session for each request.");
}

/* (non-Javadoc)
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {

// Try to get a Hibernate Session from the HttpSession
HttpSession userSession =
((HttpServletRequest) request).getSession();
Session hibernateSession =
(Session) userSession.getAttribute(HTTPSESSIONKEY);


try {

if (hibernateSession != null){
HibernateUtil.reconnect(hibernateSession);
}

// If there is no Session, the first call to
// HibernateUtil.beginTransaction in application code will open
// a new Session for this thread.

// try {
chain.doFilter(request, response);

// Commit any pending database transaction.
HibernateUtil.commitTransaction();

} catch (LomisDataAccessException e){
log.error("Fehler beim Transaktions-Commit im HibernateSessionFilter");
try {
HibernateUtil.getSession().close();
} catch (HibernateException he){
log.error(he);
} catch (Exception ex) {
throw new ServletException();
}

} finally {
// TODO: The Session should be closed if a fatal exceptions occurs

// No matter what happens, disconnect the Session.

try {
hibernateSession = HibernateUtil.disconnectSession();
} catch (Exception e) {
log.error("Fehler beim Disconnect der Session in HibernateSessionFilter");
}
// and store it in the users HttpSession
userSession.setAttribute(HTTPSESSIONKEY, hibernateSession);
}
}

/* (non-Javadoc)
* @see javax.servlet.Filter#destroy()
*/
public void destroy() {
}

}


The next file is the hibernateutil class:
package com.ebn.lomis.server.hibernate.util;

import org.apache.commons.logging.*;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import com.ebn.lomis.common.exceptions.LomisDataAccessException;

import javax.naming.*;

/**
* Basic Hibernate helper class, handles SessionFactory, Session and Transaction.
* <p>
* Uses a static initializer for the initial SessionFactory creation
* and holds Session and Transactions in thread local variables. All
* exceptions are wrapped in an unchecked InfrastructureException.
*
* @author christian@hibernate.org
*/
public class HibernateUtil {

private static Log log = LogFactory.getLog(HibernateUtil.class);

private static Configuration configuration;
private static SessionFactory sessionFactory;
private static final ThreadLocal threadSession = new ThreadLocal();
private static final ThreadLocal threadTransaction = new ThreadLocal();
private static final ThreadLocal threadInterceptor = new ThreadLocal();

// Create the initial SessionFactory from the default configuration files
static {
try {
configuration = new Configuration();
sessionFactory = configuration.configure().buildSessionFactory();
// We could also let Hibernate bind it to JNDI:
// configuration.configure().buildSessionFactory()
} catch (Throwable ex) {
// We have to catch Throwable, otherwise we will miss
// NoClassDefFoundError and other subclasses of Error
log.error("Building SessionFactory failed.", ex);
throw new ExceptionInInitializerError(ex);
}
}

/**
* Returns the SessionFactory used for this static class.
*
* @return SessionFactory
*/
public static SessionFactory getSessionFactory() {
/* Instead of a static variable, use JNDI:
SessionFactory sessions = null;
try {
Context ctx = new InitialContext();
String jndiName = "java:hibernate/HibernateFactory";
sessions = (SessionFactory)ctx.lookup(jndiName);
} catch (NamingException ex) {
throw new InfrastructureException(ex);
}
return sessions;
*/
return sessionFactory;
}

/**
* Returns the original Hibernate configuration.
*
* @return Configuration
*/
public static Configuration getConfiguration() {
return configuration;
}

/**
* Rebuild the SessionFactory with the static Configuration.
*
*/
public static void rebuildSessionFactory()
throws LomisDataAccessException {
synchronized(sessionFactory) {
try {
sessionFactory = getConfiguration().buildSessionFactory();
} catch (Exception ex) {
throw new LomisDataAccessException(ex);
}
}
}

/**
* Rebuild the SessionFactory with the given Hibernate Configuration.
*
* @param cfg
*/
public static void rebuildSessionFactory(Configuration cfg)
throws LomisDataAccessException {
synchronized(sessionFactory) {
try {
sessionFactory = cfg.buildSessionFactory();
configuration = cfg;
} catch (Exception ex) {
throw new LomisDataAccessException(ex);
}
}
}

/**
* Retrieves the current Session local to the thread.
* <p/>
* If no Session is open, opens a new Session for the running thread.
*
* @return Session
*/
public static Session getSession()
throws LomisDataAccessException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
log.debug("Opening new Session for this thread.");
if (getInterceptor() != null) {
log.debug("Using interceptor: " + getInterceptor().getClass());
s = getSessionFactory().openSession(getInterceptor());
} else {
s = getSessionFactory().openSession();
}
threadSession.set(s);
}
} catch (HibernateException ex) {
throw new LomisDataAccessException(ex);
}
return s;
}

/**
* Closes the Session local to the thread.
*/
public static void closeSession()
throws LomisDataAccessException {
try {
Session s = (Session) threadSession.get();
threadSession.set(null);
if (s != null && s.isOpen()) {
log.debug("Closing Session of this thread.");
s.close();
}
} catch (HibernateException ex) {
throw new LomisDataAccessException(ex);
}
}

/**
* Start a new database transaction.
*/
public static void beginTransaction()
throws LomisDataAccessException {
Transaction tx = (Transaction) threadTransaction.get();
try {
if (tx == null) {
log.debug("Starting new database transaction in this thread.");
tx = getSession().beginTransaction();
threadTransaction.set(tx);
}
} catch (HibernateException ex) {
throw new LomisDataAccessException(ex);
}
}

/**
* Commit the database transaction.
*/
public static void commitTransaction()
throws LomisDataAccessException {
Transaction tx = (Transaction) threadTransaction.get();
try {
if ( tx != null && !tx.wasCommitted()
&& !tx.wasRolledBack() ) {
log.debug("Committing database transaction of this thread.");
tx.commit();
}
threadTransaction.set(null);
} catch (HibernateException ex) {
rollbackTransaction();
throw new LomisDataAccessException(ex);
}
}

/**
* Commit the database transaction.
*/
public static void rollbackTransaction()
throws LomisDataAccessException {
Transaction tx = (Transaction) threadTransaction.get();
try {
threadTransaction.set(null);
if ( tx != null && !tx.wasCommitted() && !tx.wasRolledBack() ) {
log.debug("Tyring to rollback database transaction of this thread.");
tx.rollback();
}
} catch (HibernateException ex) {
throw new LomisDataAccessException(ex);
} finally {
closeSession();
}
}

/**
* Reconnects a Hibernate Session to the current Thread.
*
* @param session The Hibernate Session to be reconnected.
*/
public static void reconnect(Session session)
throws LomisDataAccessException {
try {
session.reconnect();
threadSession.set(session);
} catch (HibernateException ex) {
throw new LomisDataAccessException(ex);
}
}

/**
* Disconnect and return Session from current Thread.
*
* @return Session the disconnected Session
*/
public static Session disconnectSession()
throws LomisDataAccessException {

Session session = getSession();
try {
threadSession.set(null);
if (session.isConnected() && session.isOpen())
session.disconnect();
} catch (HibernateException ex) {
throw new LomisDataAccessException(ex);
}
return session;
}

/**
* Register a Hibernate interceptor with the current thread.
* <p>
* Every Session opened is opened with this interceptor after
* registration. Has no effect if the current Session of the
* thread is already open, effective on next close()/getSession().
*/
public static void registerInterceptor(Interceptor interceptor) {
threadInterceptor.set(interceptor);
}

private static Interceptor getInterceptor() {
Interceptor interceptor =
(Interceptor) threadInterceptor.get();
return interceptor;
}

}


The long session concept is functioning within a single user session. My problem is situated between two or more user session. Each session becomes no notice from the update of the data from other session. My thought as I decided to use Hibernate for my project was that Hibernate do the communitation of changes to other session and that I haven't to inform other sessions about any changes. From this point of view I think that I haven't set the correct setting up to now.

Following you will find the load function in the struts action:
protected void loadFormBean(ActionContext ctx) {
BaseListForm form;
Vector<DataObject> vctDataobject= null;
ArrayList alsViewhelpers;
FilterContainer filterContainer;
ListDataModel model;
Vector<ViewHelper> vctViewhelpers = new Vector<ViewHelper>(0);

form = this.getForm(ctx);
if (form != null) {
try {
filterContainer=this.getFilterContainer(this.getSessionUser(ctx));

//filterContainer.add(this.getDeaktivFilterValue());

vctDataobject=getDao().findFiltered(filterContainer);
for (DataObject e: vctDataobject){
ViewHelper vh=getBusinessViewHelper(ctx,e);
vctViewhelpers.add(vh);
}
} catch (Exception e) {
e.printStackTrace();
ClientExceptionHandler.addGlobalError(ctx,"error.load",
e,BaseListAction.class);
}

model = new ListDataModel(vctViewhelpers);
SimpleListControl slc = new SimpleListControl();
slc.setDataModel(model);
form.setSlclist(slc);
}
System.out.println("Load form beendet");
}

With each server crossing I do a access to the database (findfiltered), create a new datamodel, create a new Listcontrol and the the list to the form. For the frontend I use Common Controls API.

Following you see the findfiltered method:
public Vector<T> findFiltered(FilterContainer cont) throws DataAccessException {
FilterContainer tmpcont;
log.info("Database request: findFiltered: \n");
List<T> list=new ArrayList<T>(0);
Vector<T> newVec=null;
Criteria crit;
if (cont==null){
tmpcont=new FilterContainer();
} else {
tmpcont=cont;
}
log.info("Database request: findFiltered: Filter:" + cont.toString()+"\n");
try {
HibernateUtil.beginTransaction();
this.session.clear();
crit = this.session.createCriteria(getPersistentClass());
for (FilterValue e : tmpcont) {
Criterion criterion=getExpression(e);
crit.add(criterion);
}
list=crit.list();
int tempsize=list.size();
log.info("Resultset size: " + tempsize + "\n");//list.size()+"\n");
} catch (Exception e) {
this.session.clear();
throw new DataAccessException(
ExceptionKeys.errorLoadData,
e,
GenericHibernateDAO.class);
}
newVec=new Vector<T>(list);
return newVec;
}


To persist the data I use following method:
public void saveOrupdate(T entity) throws LomisDataAccessException {
log.info("Database request: saveOrupdate: \n");
try {
HibernateUtil.beginTransaction();
this.session.saveOrUpdate(entity);
this.session.flush();
this.session.refresh(entity);
log.info("Objekt gespeichert: "+entity.toString());

} catch (Exception e) {
this.session.clear();
throw new DataAccessException(
ExceptionKeys.errorSaveData,
e,
GenericHibernateDAO.class);
}
}


I hope this code help for a diagnosis. I think I use Hibernate In a wrong way. There is an setting I haven't found.

The problem is on the level between the different user session and their view to their own data. Updates of other data will not become visible for these session, although the data is persitent in the database.

I hope you can locate the mistake. Otherwise I will delete all lazy loading code and program explicit loading for each subselect.

Thanks in advance Thomas


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 12, 2006 2:13 pm 
Newbie

Joined: Tue May 24, 2005 11:25 am
Posts: 16
yallatop wrote:
Hello,
1. No, I didn't use Oracle, I use Mysql as database.


Sorry cant' help you with this one then. I actually suggested you another O/R mapper, but it works with Oracle only.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.