-->
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.  [ 2 posts ] 
Author Message
 Post subject: Inheritance/Boolean Discriminator
PostPosted: Fri Jan 02, 2009 1:11 pm 
Newbie

Joined: Thu Jan 01, 2009 9:01 pm
Posts: 2
Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp

Hibernate version:
3.2.5.ga

Mapping documents:
Code:
<hibernate-mapping>
    <class name="com.company.data.User" table="user" catalog="mydb" discriminator-value="false">
        <cache usage="nonstrict-read-write"/>
        <id name="id" type="java.lang.Long">
            <column name="id" />
            <generator class="identity" />
        </id>
        <discriminator column="member" type="boolean" />
        <property name="anonymous" type="boolean">
            <column name="anonymous" not-null="true" />
        </property>
        <property name="emailAddress" type="string">
            <column name="email_address" not-null="true" />
        </property>
        <property name="firstName" type="string">
            <column name="first_name" />
        </property>
        <property name="lastName" type="string">
            <column name="last_name" />
        </property>
        <property name="bozo" type="boolean">
            <column name="bozo" not-null="true" />
        </property>
    </class>
</hibernate-mapping>


Code:
<hibernate-mapping>
        <subclass name="com.company.data.Member" extends="com.company.data.User" discriminator-value="true">
            <join table="member" catalog="mydb">
                <key column="id"/>
                <property name="username" type="string">
                    <column name="username" not-null="true">
                        <comment>the login username of the user</comment>
                    </column>
                </property>
                <property name="password" type="string">
                    <column name="password" length="64" not-null="true">
                        <comment>the login password of the user</comment>
                    </column>
                </property>
                <property name="createdAt" type="timestamp">
                    <column name="created_at" length="19" not-null="true">
                        <comment>the date the user was created</comment>
                    </column>
                </property>
                <property name="updatedAt" type="timestamp">
                    <column name="updated_at" length="19" />
                </property>
                <many-to-one class="com.company.data.Role" fetch="select" name="role">
                    <column name="role_id">
                        <comment>the role of the member</comment>
                    </column>
                </many-to-one>
            </join>
      </subclass>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():
Code:
       Session session = HibernateUtil.getCurrentSession();
       session.beginTransaction();
       User user = (User)session.load(User.class, id);
       session.getTransaction().commit();
       return user;


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


With the above mapping, when I set some Users to have their member column be "true" and some be "false" (it is actually a BIT(1) column with 1 or 0), user.isMember() ALWAYS returns false.

Also, the below code always throws the ClassCastException:
Code:
                        Member member = (Member)post.getAuthor();
                        out.println(member.getFirstName() + ": member");
                        }catch(ClassCastException e){
                            out.println(post.getAuthor().getFirstName() + ": user");
                            }


However, when I change the discriminator values on the superclass/subclass to be 1 or 0, I get the following HibernateException:

Code:
org.hibernate.WrongClassException: Object with id: 2 was not of the specified subclass: com.company.data.User (Discriminator: true)
   org.hibernate.loader.Loader.getInstanceClass(Loader.java:1453)
   org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1284)
   org.hibernate.loader.Loader.getRow(Loader.java:1206)
   org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:580)
   org.hibernate.loader.Loader.doQuery(Loader.java:701)
   org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
   org.hibernate.loader.Loader.loadEntity(Loader.java:1860)
   org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48)
   org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42)
   org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3044)
   org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:395)
   org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:375)
   org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)
   org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:98)
   org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
   org.hibernate.impl.SessionImpl.immediateLoad(SessionImpl.java:836)
   org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:66)
   org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111)
   org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:150)
   com.company.data.User$$EnhancerByCGLIB$$48c74ea3.isMember(<generated>)
   org.apache.jsp.ForumListTest_jsp._jspService(ForumListTest_jsp.java:111)
   org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
   javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
   org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
   org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
   org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
   javax.servlet.http.HttpServlet.service(HttpServlet.java:717)


As you can see here, it detects the column value as "true", where it says "(Discriminator: true)". So, why wasn't it working the way it was setup before? Why was it outputting "false" for user.isMember() and why will it not return a Member instance, rather than a User instance?

Any help is appreciated!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 02, 2009 4:53 pm 
Red Hat Associate
Red Hat Associate

Joined: Mon Aug 16, 2004 11:14 am
Posts: 253
Location: Raleigh, NC
The discriminator column is used by Hibernate to persist information on the type of the hydrated entity for a single-table hierarchy. If you want a User to be a Member, you must create it AS a Member; you can't just flip a switch and have one class become another.

Consider refactoring this mapping into something like User and MemberInfo where everyone is a User and only Members have a MemberInfo attribute reflecting their state.

If you stick with your setup, you'd have to delete a User and re-insert it as a Member in order to change. You could of course change the data outside Hibernate and re-read it but that kinda flies in the face of what Hibernate is for :)

-Chris

_________________
Chris Bredesen
Senior Software Maintenance Engineer, JBoss


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