-->
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.  [ 4 posts ] 
Author Message
 Post subject: Hibernate automatically deleting foreign key
PostPosted: Mon Jul 25, 2005 1:10 pm 
Beginner
Beginner

Joined: Fri Jun 04, 2004 12:50 pm
Posts: 32
Hi all,

I have a problem where hibernate is automatically setting the foreign key value to null after the objects are used. It is quite bizarre. As far as I know in my code I do not set them to null at any point or delete them.

I have a Search and a SearchItem object. They are used to display search criteria on a jsp page. I go and get the objects and use them the first time. Everything is fine. But, when I try to use them again the SearchItem objects no longer exist because somehow their foreign key values have been set to null.

They are still in the database. The rows do not get deleted. But their foreign key which links them to Search is null

Things to note: I create a sessionfactory and place it in JNDI. Then, whenever I need a session I use that sessionFactory with .openSession(). I never close() the session out because I want to take advantage of the laziness. (I think this is the correct way of going about doing things but may be wrong)

Any help greatly appreciated.


Hibernate version:
Whichever version comes with JBoss 4.0.2. I think its hibernate 2.1 but may be wrong.

Mapping documents:

SEARCH OBJECT

<class name="com.camp.common.search.Search" table="tblSearch">

<id name="searchID" type="integer">
<column name="id_search" sql-type="integer" not-null="true"/>
<generator class="sequence">
<param name="sequence">tblsearch_id_search_seq</param>
</generator>
</id>

<property name="searchName">
<column name="name" sql-type="char(128)" not-null="true"/>
</property>

<property name="searchDisplayName">
<column name="display_name" sql-type="char(128)" not-null="true"/>
</property>

<set name="searchItems" sort="com.camp.common.search.SearchItemComparator" >
<key column="fk_id_search"/>
<one-to-many class="com.camp.common.search.SearchItem"/>
</set>

</class>

SEARCHITEM OBJECT

<class name="com.camp.common.search.SearchItem" table="tblSearchItem">

<id name="searchID" unsaved-value="null">
<column name="id_search_item" sql-type="integer" not-null="true"/>
<generator class="sequence">
<param name="sequence">tblsearchitem_id_search_item_seq</param>
</generator>
</id>

<property name="objectClass" type="string">
<column name="object_class" sql-type="char(64)" not-null="true"/>
</property>
<property name="objectSetField" type="string">
<column name="object_Set_field" sql-type="char(128)" not-null="true"/>
</property>
<property name="objectField" type="string">
<column name="object_field" sql-type="char(128)" not-null="true"/>
</property>
<property name="userObjectFieldName" type="string">
<column name="user_object_field_name" sql-type="char(64)" not-null="true"/>
</property>
<property name="displayName" type="string">
<column name="display_name" sql-type="char(64)" not-null="true"/>
</property>
<property name="type" type="string">
<column name="type" sql-type="char(64)" not-null="true"/>
</property>
<property name="viewType" type="string">
<column name="view_type" sql-type="char(64)" not-null="true"/>
</property>
<property name="position" type="integer">
<column name="position" sql-type="integer" not-null="true"/>
</property>

<many-to-one name="search" class="com.camp.common.search.Search" column="fk_id_search" not-null="true"/>

</class>

Code between sessionFactory.openSession() and session.close():

Context ctx = new InitialContext();
sessionFactory = ((SessionFactory) ctx.lookup("java:/CAMP/HibernateFactory")).openSession();
session.setFlushMode(FlushMode.ALWAYS);
session.setCacheMode(CacheMode.REFRESH);

Session sess = sessionFactory.openSession();

Criteria crit = sess.createCriteria("com.camp.common.search.Search");
entities = crit.list();
log.info("Finished getting entities");

Note that I never call session.close() because I want to keep it open all the time

Name and version of the database you are using:
Postgres 8.0

The generated SQL (show_sql=true):

This is the SQL that SHOULDN'T happen but does automatically
"update tblSearchItem set fk_id_search=null where fk_id_search=?"

Debug level Hibernate log excerpt:


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 26, 2005 12:08 am 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
When you say you "use [the SearchItems] again", is that after another web page submit? Are you sure you're in the same thread? If not then the lazy references will be broken. If you put the Search and SearchItem objects into a web context, then retrieve them from it after the next submission, their links won't be guaranteed to survive, especially if they've been proxied and haven't yet been initialized by CGLib.

If you app is going to scale at all, then lots of openSession calls and no closeSessions is going to cause you problems, even with flush=always. Also, it'll be very fragile: if there's any strangeness to your data, something like a delete attempt foiled by referential integrity, then your session will be essentially unusable. If you never close it, anything could happen. Expect problems.

It is probable that what you want is a large 2nd-level cache (ehcache or similar) shared between multiple sessions. Check the docs for the correct solution. They are quite explicit on this: Hibernate sessions are not intended to stay around beyond a single web page action, or action similar duration. All you need to do is keep a single SessionFactory around, which maintains a reference to a common cache. Then each Session opened by the factory will be able to share the context of the cache.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 26, 2005 10:27 am 
Beginner
Beginner

Joined: Fri Jun 04, 2004 12:50 pm
Posts: 32
Hi Tenwit,

Thanks for the great answer. When I say I use them again what I mean is that I will in the future have to use the objects again, and to do that I go and try to retrieve them from the database. Although I do put them in the web context for the intial page view, after that page is complete I "throw them away" meaning I remove them from the session. If I need them again I go and get them again from the db.

These SearchItem and Search objects should never be changed. They are supposed to always stay the same.

I am using struts and hibernate. I really do not touch threading at all but rather leave that to the container and frameworks.

Thanks for the info on opening and closing sessions. I seemed to be getting errors when I closed a session and then some lazy initializing needed to take place. That is why I thought they had to be open all the time. It makes sense about the 2nd Level cache. I guess I either never got it set up right or never really understood it.

Cheers


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 26, 2005 10:30 am 
Beginner
Beginner

Joined: Fri Jun 04, 2004 12:50 pm
Posts: 32
I have just tried to make sure that all my sessions get closed and when I run my app the following error occurs.

08:28:22,436 INFO [STDOUT] org.hibernate.HibernateException: Session is closed
at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:103)
at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:86)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1129)
at org.hibernate.loader.Loader.doQuery(Loader.java:373)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:210)
at org.hibernate.loader.Loader.doList(Loader.java:1561)
at org.hibernate.loader.Loader.list(Loader.java:1544)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:111)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1306)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:299)
at com.camp.server.entity.EntityBackEnd.getEntities(Unknown Source)
at com.camp.helpers.entity.EntityHelper.getEntities(Unknown Source)
at com.camp.actions.login.LogonAction.execute(Unknown Source)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:81)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:39)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:153)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:59)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
at java.lang.Thread.run(Thread.java:534)
08:28:22,436 INFO [EntityBackEnd] Leaving getEntities
08:28:22,436 INFO [STDOUT] java.lang.NullPointerException
08:28:22,436 INFO [STDOUT] at com.camp.common.config.global.GlobalSettings.<init>(Unknown Source)
08:28:22,436 INFO [STDOUT] at com.camp.actions.login.LogonAction.execute(Unknown Source)

I think this was the exact reason I didn't think the sessions should be closed. I guess some caching schemes and session understanding is on course for the next few days for me.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 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.