-->
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: Howto:Intercept BEFORE Interceptor (to set orphan's parent)
PostPosted: Thu Dec 30, 2004 11:11 am 
Beginner
Beginner

Joined: Wed Aug 27, 2003 3:46 am
Posts: 34
Location: Taiwan
Hi , I have a legacy PHP forum (just like classical User/Board/Post forum) , I want to use Hibernate to map the forum to Java classes.

The schema is simple : The POST TABLE has two fields link to USER / BOARD TABLE's primary keys , indicating the poster and the board containg it.
But some posts' POSTER value cannot be found in USER.NUMBER , meaning these posts are orphan posts.

I don't want to lose these posts , and want to give them a DUMMY Poster.

To achieve this , I write an interceptor like this :

Code:
public class PostInterceptor implements Interceptor
{
  public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException
  {
    if (entity instanceof Post)
    {       
        if (("timestamp").equals( propertyNames[i]))
        //..... (another intercept method) ........
        if (("poster").equals( propertyNames[i]))
        {
          if (state[i] == null)
          {
            User u = new User();
            u.setNumber(1);
            u.setLoginName("Invalid_User");
            u.setUsername ("Invalid_User");
            u.setEmail("INVALID@NON_EXIST.COM");
            u.setPassword("XXX");
            u.setStatus("INVALID");
            u.setTitle("INVALID");
            state[i] = u;
          }
        }
      }
    }//if
    return false;
  }
}

I think it should be OK , but when running , hibernate throws this exception :

org.springframework.orm.hibernate.HibernateObjectRetrievalFailureException: No row with the given identifier exists: 9169, of class: forum.User; nested exception is net.sf.hibernate.UnresolvableObjectException: No row with the given identifier exists: 9169, of class: forum.User

I know this is because hibernate finds a Post whose PosterId = 9169 , and cannot find a User.Number = 9169 ....
But it seems Interceptor cannot intercept post.setUser() ... (other methods can be intercepted , such as post.setTimestamp()...)

How do I solve this ?


Hibernate version:2.1.6 with Spring 1.1.3

Mapping documents:
Code:
   <class name="Post" table="Posts">
      <cache usage="read-only"/>
      <id name="number" column="B_Number" type="long">
         <generator class="native"/>
      </id>
      <property    name="subject"   column="B_Subject"  type="java.lang.String"/>
      <property    name="body"      column="B_Body"     type="java.lang.String"/>
      <property    name="timestamp" column="B_Posted"   type="long"/>
      <many-to-one name="poster"    column="B_PosterId" class="User" not-null="false"/>
      <many-to-one name="board"     column="B_Board"    class="Board"/>
   </class>



   <bean id="postInterceptor" class="forum.hibernate.PostInterceptor" />
   
   <bean id="postHibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor">
      <property name="sessionFactory">
         <ref bean="mySessionFactory"/>
      </property>
      <property name="entityInterceptorBeanName">
         <value>postInterceptor</value>
      </property>
   </bean>
   
   <bean id="postDaoImpl" class="forum.hibernate.PostDaoImpl">
      <property name="sessionFactory">
         <ref local="mySessionFactory"/>
      </property>
   </bean>


   <bean id="postDao" class="org.springframework.aop.framework.ProxyFactoryBean">
      <property name="proxyInterfaces">
         <value>forum.dao.PostDao</value>
      </property>
      <property name="interceptorNames">
         <list>
            <value>postHibernateInterceptor</value>
            <value>postDaoImpl</value>
         </list>
      </property>
   </bean>


Code between sessionFactory.openSession() and session.close():
Spring :
Code:
  public Post getPost(final long number)
  {
    return (Post) this.getHibernateTemplate().execute
    (
      new HibernateCallback()
      {
        public Object doInHibernate(Session session) throws HibernateException
        {
          try
          {
            return session.load(Post.class , new Long(number));
          }
          catch (ObjectNotFoundException e)
          {
            return null;
          }
        }
      }
    );
  }


Full stack trace of any exception that occurs:

Name and version of the database you are using:
MySQL 3.23.58

The generated SQL (show_sql=true):

Debug level Hibernate log excerpt:


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 31, 2004 4:49 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
Answering the question from the unneeded jira entry you created:

Quote:
To make the post short , it means that in a legacy database , there maybe some table with invalid FK (maybe null or maybe points to a non-exist row). It means broken data model.

It seems that , currently Interceptor.onLoad() cannot intercept these error . Is it possible to work around this ? or provide some lower level interceptor to intercept the invalid FK problem ?


It would try to look into UserTypes in H2.
In H3 we have the event system that provides all kind of weird hooks ,)

(what about running a update that removes those invalid references and restore the integrity of the database ?)

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 31, 2004 10:40 am 
Beginner
Beginner

Joined: Wed Aug 27, 2003 3:46 am
Posts: 34
Location: Taiwan
max wrote:
Answering the question from the unneeded jira entry you created:

It would try to look into UserTypes in H2.
In H3 we have the event system that provides all kind of weird hooks ,)

(what about running a update that removes those invalid references and restore the integrity of the database ?)


Thank you for replying...
But I found some cons in using UserTypes in H2 :

First , I will lose <many-to-one> , because UserType is only acceptable in <property>

Second, if I use UserType , I'll have to do database query in nullSafeGet() . I am using Spring , and I cannot inject SessionFactory to UserType, because UserType is instantiated by Hibernate, which doesn't know anything about Spring.
I found some discussion about solving this problem , but those seem complicated, and seems not a good design...

Third , I don't want to open Spring's BeanFactory/ApplicationContext in nullSafeGet() , I think it is a bad idea...


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 31, 2004 11:09 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
crazy idea: look at ManyToOneType - it is just a type like anything else - i actually haven't chekked what will happen if you make your UserType extend ManyToOneType - I would think it could be made to work.

I actually haven't tried this - but don't have time because the new year is coming here ,)

_________________
Max
Don't forget to rate


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.