-->
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.  [ 11 posts ] 
Author Message
 Post subject: ClassCastException - migration from 2.1.8 to 3.0
PostPosted: Fri Apr 15, 2005 8:54 am 
Beginner
Beginner

Joined: Wed Aug 18, 2004 10:03 am
Posts: 28
Hibernate version: 3.0

Mapping documents:

Code:
<hibernate-mapping>
    <class
        name="com.mobilitysol.uy.check_manager.domain.CheckType"
        table="CHECK_TYPE">
   
        <id name="id" column="uid">
            <generator class="uuid.hex"/>
        </id>

        <discriminator column="type_id"/>
            
        <subclass
            name="com.mobilitysol.uy.check_manager.domain.Defered"
            discriminator-value="1">
               
            <property
                name="expireDate"
                type="com.maiasoft.uy.pml.hibernate.DateOnlyType"/
            >                  

        </subclass>    
            
        <subclass
            name="com.mobilitysol.uy.check_manager.domain.AtDay"
            discriminator-value="2">      
        </subclass>             
   
    </class>

</hibernate-mapping>


Code:
<hibernate-mapping>

    <class
        name="com.mobilitysol.uy.check_manager.domain.Check"
        table="CHECKS">
     
        <id name="id" column="uid">
            <generator class="uuid.hex"/>
        </id>

        <discriminator column="type_id"/>

        ... irrelevant properties ...                                                            
        ... irrelevant many-to-one ...

        <many-to-one
            name="checkType"
            column="checktype_uid"
            class="com.mobilitysol.uy.check_manager.domain.CheckType"
            cascade="delete"
        />            
            
   <subclass
            name="com.mobilitysol.uy.check_manager.domain.Received" 
            discriminator-value="1">

                ... irrelevant properties ...               
          
        </subclass>
            
   <subclass   
            name="com.mobilitysol.uy.check_manager.domain.Emitted"
            discriminator-value="2">

            <property name="checkBookNumber"/>
               
        </subclass>             
   
    </class>

</hibernate-mapping>


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

CheckType is abstract, and have an abstract method called getCheckType that return an integer, this method is implemented by Defered and by AtDay

Into a Check class i make this...

Code:
    if (checkType.getCheckType() == CheckTypes.DEFFERED) {
        ...
        ... ((Defered) checkType) ...
        ...
    }


I probe with instanceof too and the problem is the same. When i call getCheckType Deffered.getCheckType is called, but, then, i cast it to Deffered and i have the ClassCastException.

Full stack trace of any exception that occurs:

Code:
java.lang.ClassCastException: com.mobilitysol.uy.check_manager.domain.CheckType$$EnhancerByCGLIB$$b2b60f2e
   at com.mobilitysol.uy.check_manager.domain.Received.getCheckInfoHeavy(Received.java:132)
   at com.mobilitysol.uy.check_manager.domain.managers.CheckManager.getCheckInfoHeavy(CheckManager.java:228)
   at com.mobilitysol.uy.check_manager.domain.CheckMgtTest.testAgregarCheck(CheckMgtTest.java:186)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at junit.framework.TestCase.runTest(TestCase.java:154)
   at junit.framework.TestCase.runBare(TestCase.java:127)
   at junit.framework.TestResult$1.protect(TestResult.java:106)
   at junit.framework.TestResult.runProtected(TestResult.java:124)
   at junit.framework.TestResult.run(TestResult.java:109)
   at junit.framework.TestCase.run(TestCase.java:118)
   at junit.framework.TestSuite.runTest(TestSuite.java:208)
   at junit.framework.TestSuite.run(TestSuite.java:203)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:421)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:305)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:186)


Name and version of the database you are using:

HSQLDB 1.7.3.3

The generated SQL (show_sql=true):

Code:
Hibernate: insert into CHECK_TYPE (expireDate, type_id, uid) values (?, '1', ?)
Hibernate: insert into CHECKS (entryDate, emissionDate, rejectionDate, number, serie, holder, receiverName, cost, currency, state, rejectionReason, observation, accountNumber, subsidiary_uid, checktype_uid, applicationType, appliedDate, type_id, uid) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '1', ?)
Hibernate: update CHECKS set emitts_uid=? where uid=?
Hibernate: select check0_.uid as uid, check0_.entryDate as entryDate2_, check0_.emissionDate as emission4_2_, check0_.rejectionDate as rejectio5_2_, check0_.number as number2_, check0_.serie as serie2_, check0_.holder as holder2_, check0_.receiverName as receiver9_2_, check0_.cost as cost2_, check0_.currency as currency2_, check0_.state as state2_, check0_.rejectionReason as rejecti13_2_, check0_.observation as observa14_2_, check0_.accountNumber as account15_2_, check0_.subsidiary_uid as subsidiary16_2_, check0_.checktype_uid as checktype17_2_, check0_.applicationType as applica18_2_, check0_.appliedDate as applied19_2_, check0_.checkBookNumber as checkBo20_2_, check0_.type_id as type2_ from CHECKS check0_, SUBSIDIARY subsidiary1_, BANK bank2_ where (check0_.number='7777' and check0_.serie='12A' and bank2_.code='1'  and check0_.subsidiary_uid=subsidiary1_.uid and subsidiary1_.bank_uid=bank2_.uid)
Hibernate: select checktype0_.uid as uid0_, checktype0_.expireDate as expireDate3_0_, checktype0_.type_id as type2_0_ from CHECK_TYPE checktype0_ where checktype0_.uid=?


I will that the information will be sufficient.

regards
epsino


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 15, 2005 9:17 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
read the migration guide and you will find lazy/proxying is now default and thus instanceof can in some cases not be performed (read in HiA about it)

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 15, 2005 10:03 am 
Beginner
Beginner

Joined: Wed Aug 18, 2004 10:03 am
Posts: 28
I read hibernate 3 migration guide, and only say that lazy is now by default.

Then, i suppose that HiA is hibernate annotations, but, i not found nothing.

I read hibernate 3 guide too, and only say that lazy is now by default too.

I not found nothing about inhertinence...

Can you help me ?

best regards and very thank you for your help
epsino


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 15, 2005 11:47 am 
Beginner
Beginner

Joined: Wed Aug 18, 2004 10:03 am
Posts: 28
You say that if i not acces first to object checkType, i can't use instanceof ?

If you say YES, i understand, but, in my code, first i use the object, and then i cast the object...

Code:
int type = checkType.getType();
Deferred oDeferred = (Deferred) checkType;


And this throw ClassCastException...

regards
epsino


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 15, 2005 12:21 pm 
Beginner
Beginner

Joined: Wed Aug 18, 2004 10:03 am
Posts: 28
I solve my problem.

Put lazy="false" on CheckType class.

thanks for all
regards
epsino


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 20, 2005 5:07 am 
Regular
Regular

Joined: Mon Sep 20, 2004 8:42 am
Posts: 58
Location: Boston, US
max wrote:
Quote:
read the migration guide and you will find lazy/proxying is now default and thus instanceof can in some cases not be performed


Not sure I understand why instanceof / downcast cannot be performed. I am getting a ClassCastException even after setting a proxy class on the subclass element. Below is a slightly modified version of the users original mapping. Note that I've added a "proxy" attribute to the subclass element.

Even after doing so, when a "Check" object loads the assocation collection of checkTypes, all the lazily loaded elements of the checkTypes are proxied on the "foo.CheckType" class on not "foo.Defered" or "foo.AtDay".

I understand that these elements are proxied and so are initialized lazily however Hibernate should be able to create proxies of the appropriate subclass by reading the discriminator values of the associated checkTypes rows. All the remaining properties on the proxy can still be lazily fetched.

Given the current behaviour of not being able to create a proxy of the appropriate subclass type, it makes it meaningless to have lazily loaded classes with subclass elements as my application code cannot downcast to foo.AtDay or foo.Defered and access the subclass specific properties.

It seems like with the existing behavior a user using "subclass" will always have to mark these as lazy="false" to do anything meaningful.

Please clarify.

Thanks,
Sanjiv

Code:
<hibernate-mapping>
    <class
        name="foo.CheckType"
        table="CHECK_TYPE">
   
        <id name="id" column="uid">
            <generator class="uuid.hex"/>
        </id>

        <discriminator column="type_id"/>
           
        <subclass
            name="foo.Defered"
            discriminator-value="1"
            proxy="foo.Defered">
               
            <property
                name="expireDate"
                type="foo.DateOnlyType"/
            >                 

        </subclass>   
           
        <subclass
            name="foo.AtDay"
            discriminator-value="2"
             proxy="foo.AtDay"
            >     
        </subclass>             
   
    </class>

</hibernate-mapping>


<hibernate-mapping>

    <class
        name="foo.Check"
        table="CHECKS">
     
        <id name="id" column="uid">
            <generator class="uuid.hex"/>
        </id>

        <discriminator column="type_id"/>

        <many-to-one
            name="checkType"
            column="checktype_uid"
            class="foo.CheckType"
            cascade="delete"
        />                             
   
    </class>

</hibernate-mapping>



Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 20, 2005 6:04 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
if you want hibernate to read the type from the database then set lazy="false" ....

having hibernate go to the database to read just one single column is not in any way efficient - we could just as well read the whole row....db operations are expensive you know ;)

/max

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 20, 2005 9:20 am 
Regular
Regular

Joined: Mon Sep 20, 2004 8:42 am
Posts: 58
Location: Boston, US
Quote:
having hibernate go to the database to read just one single column is not in any way efficient - we could just as well read the whole row....db operations are expensive you know ;)


I see your point. However when using discriminators, you typically want to create a non-unique index on the discriminator column as queries are frequently going to be run with the discriminator column in the where criteria.

Hibernate would only need to read the discriminator column from the table when deciding what proxy type to create and this would be much efficient than reading the entire row since you're reading only the rowid from the (BTree) index and not reading data blocks from the table itself.

And in a 1-many relationship, a bunch of rowids will be selected in a single query which will be much more efficient than reading all the rows.

Assuming that the underlying schema does have indexes and behaves as above would be too much for Hibernate to assume so I'm okay with setting lazy="false" for entities with <subclass> elements.

However reading only column can be much more efficient than reading the entire row :)

Thanks,
Sanjiv


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 20, 2005 9:28 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
well patches with performance numbers are always welcome ;)

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 20, 2005 9:31 am 
Regular
Regular

Joined: Mon Sep 20, 2004 8:42 am
Posts: 58
Location: Boston, US
Sure, I'll look into this sometime. The behaviour I describe would certainly make Hibernate more transparent.

Thanks,
Sanjiv


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 20, 2005 11:47 am 
Beginner
Beginner

Joined: Fri Mar 26, 2004 8:19 am
Posts: 49
Hi there. To enable instanceof behavior, use Hibernate.getRootClass or specify a proxy interface (that you create) having the methods mirrored in your persistent class. Then you can do type checking using the interfaces.


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