I am using hibernate 3.1.3 with jdk 1.4.2.09 hitting a Sybase ver 12.5 database.
I have a network of objects that has 3 classes, A, B, and C. There is a 1 to many relationship from A to B and a 1 to 1 relationship from B to C. When I have all the relationships defined with cascade="none", I can save all the objects in a database session and everything works correctly. However, if I define the relationship from B to C to be cascade="all", I get an exception because for some reason object A will be saved twice and it therefore violates a primary key constraint. When I look in the log I do see the 2 insert statements into the same table, yet I am certain that I am only saving the object once.
I am using a web client and have a servlet filter that commits the transaction and closes the session upon completion of the servlet. My guess is that it is in that code. I will include the code for my VERY SIMPLE DBUtil class that manages the connection on my behalf. Please let me know if I am doing something blatantly wrong. I will also include my Filter code. Any help will be greatly appreciated.
******************************************
public class DBUtil
{
private static DBUtil INSTANCE = new DBUtil();
private Configuration _cfg = null;
private SessionFactory _factory = null;
private ThreadLocal _session = new ThreadLocal();
private ThreadLocal _transaction = new ThreadLocal();
private boolean _autocommit = true;
private DBUtil()
{}
private Session openSession()
{
Session answer = getCurrentSession();
if (answer == null)
{
if (_factory != null)
{
DebugInterceptor i = new DebugInterceptor();
answer = _factory.openSession(i);
_session.set(answer);
}
}
return answer;
}
private Session getSession()
{
return openSession();
}
private boolean isSessionOpen()
{
return (_session.get() != null);
}
private void closeCurrentSession()
{
Session currSession = getCurrentSession();
if (currSession != null)
{
if (_autocommit)
{
commitTransaction();
} else
{
rollbackTransaction();
}
currSession.close();
_session.set(null);
}
}
private Transaction beginTransaction()
{
Transaction answer = (Transaction) _transaction.get();
if (answer == null)
{
Session session = getSession();
if (session != null)
{
answer = session.beginTransaction();
_transaction.set(answer);
}
}
return answer;
}
private Transaction getCurrentTransaction()
{
return (Transaction) _transaction.get();
}
private void commitTransaction()
{
Transaction currTxn = getCurrentTransaction();
if (currTxn != null)
{
currTxn.commit();
_transaction.set(null);
}
}
private void rollbackTransaction()
{
Transaction currTxn = getCurrentTransaction();
if (currTxn != null)
{
currTxn.rollback();
_transaction.set(null);
}
}
public static Session OpenSession()
{
return INSTANCE.openSession();
}
public static Session GetSession()
{
return INSTANCE.getSession();
}
public static Session GetCurrentSession()
{
return INSTANCE.getCurrentSession();
}
public static void CloseCurrentSession()
{
INSTANCE.closeCurrentSession();
}
public static boolean IsSessionOpen()
{
return INSTANCE.isSessionOpen();
}
public static Transaction BeginTransaction()
{
return INSTANCE.beginTransaction();
}
public static Transaction GetCurrentTransaction()
{
return INSTANCE.getCurrentTransaction();
}
public static void CommitCurrentTransaction()
{
INSTANCE.commitTransaction();
}
public static void RollbackCurrentTransaction()
{
INSTANCE.rollbackTransaction();
}
}
**************************************************
public class HibernateFilter implements Filter
{
private static final Logger LOGGER = Logger.getLogger(HibernateFilter.class);
public HibernateFilter()
{
super();
LOGGER.debug("Constructed");
}
public void init(FilterConfig config) throws ServletException
{
LOGGER.debug("init");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
LOGGER.debug("doFilter +");
try
{
DBUtil.OpenSession();
chain.doFilter(request, response);
DBUtil.CommitCurrentTransaction();
} finally
{
DBUtil.CloseCurrentSession();
}
LOGGER.debug("doFilter -");
}
public void destroy()
{
LOGGER.debug("destroy");
}
}
*******************************************************
I created an interceptor to log when an object is saved and when a transaction is begun and completed. Note that there is not afterTransactionComplete indicator
12:08:42:419|DEBUG|DebugInterceptor|afterTransactionBegin+-
12:08:42:450|DEBUG|DebugInterceptor|onSave(class Class A) +
12:08:42:450|DEBUG|DebugInterceptor|Saving A 5694 [true]
12:08:42:607|DEBUG|DebugInterceptor|onSave(class Class B) +
12:08:42:654|DEBUG|DebugInterceptor|onSave(class Class C) +
12:08:42:669|DEBUG|DebugInterceptor|onSave(class Class B) +
12:08:42:669|DEBUG|DebugInterceptor|onSave(class Class C) +
**********************************************************
Thanks for any and all help. Please be brutal - I can take it if it helps me get to the solution.
Marc.Luce@bankofamerica.com