-->
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.  [ 13 posts ] 
Author Message
 Post subject: many-to-many lazy fetching returning 'blank' objects
PostPosted: Tue Mar 29, 2005 2:24 am 
Newbie

Joined: Tue Mar 29, 2005 1:52 am
Posts: 5
Location: Melbourne, Australia
Read the rules before posting!
http://www.hibernate.org/ForumMailingli ... AskForHelp

Hibernate version:
3.0 rc1 with annotations

Mapping documents:
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>

      <!-- Don't forget to copy your JDBC driver to the lib/ directory! -->

      <!-- Settings for a remote MSSqlServer database. -->
      <property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
      <property name="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
      <property name="connection.url">jdbc:jtds:sqlserver://STAGEDB/CBAS</property>
      <property name="connection.username">cbasapp</property>
      <property name="connection.password">****</property>

      <!-- Print SQL to stdout. -->
      <property name="show_sql">true</property>

      <!-- Mapping files. -->
      <mapping class="model.Foo"/>
      <mapping class="model.Bar"/>

   </session-factory>

</hibernate-configuration>


Relevant annotations
Code:
    /* From Foo.java */
    @ManyToMany(
        fetch=FetchType.LAZY
    )
    @AssociationTable(
        table=@Table(name="FooBarRel"),
        joinColumns={@JoinColumn(name="fooId")},
        inverseJoinColumns={@JoinColumn(name="barId")}
    )
    public final Collection<Bar> getBars() {
        return bars;
    }

    /* From Bar.java */
    @ManyToMany(
        fetch=FetchType.LAZY,
        isInverse=true
    )
    @AssociationTable(
        table=@Table(name="FooBarRel"),
        joinColumns={@JoinColumn(name="barId")},
        inverseJoinColumns={@JoinColumn(name="fooId")}
    )
    public final Collection<Foo> getFoos() {
        return foos;
    }


Code between sessionFactory.openSession() and session.close():
Code:
        Foo foo = new Foo();
       
        Criteria criteria = session.createCriteria(foo.getClass());
        criteria = criteria.add(Example.create(foo));
       
        Collection results = criteria.list();
       
        for (Object o : results) {
            foo = (Foo) o;
            Collection<Bar> bars = foo.getBars();
           
            System.out.println(bars.size());
           
            for (Bar bar : bars) {
                System.out.println(bar.getId());
            }
        }


Full stack trace of any exception that occurs:

Name and version of the database you are using:
SQL Server Standard Edition v8 (SP3)

The generated SQL (show_sql=true):
Hibernate: select this_.id as id0_ from Foo this_ where (1=1)
Hibernate: select bars0_.fooId as fooId__, bars0_.barId as barId__ from FooBarRel bars0_ where bars0_.fooId=?

Debug level Hibernate log excerpt:

I have a many-to-many mapping as shown in the code snippets above using annotations. When using FetchType.LAZY as above, the collections are being initialized but filled with 'blank' objects (the fields of the objects are all null). If the database had one Foo record and one Bar record, related with a record in the FooBarRel table, the output for the above program is
Code:
1
null


If I use FetchType.EAGER, this works fine and the output of the above program is
Code:
1
1

which is what I am after.

Is there something I am not doing right here to do with lazy initialization?


Top
 Profile  
 
 Post subject: re: many-to-many lazy fetching returning 'blank' objects
PostPosted: Thu Mar 31, 2005 1:59 am 
Newbie

Joined: Tue Mar 29, 2005 1:52 am
Posts: 5
Location: Melbourne, Australia
I am still stuck on this one. Does anyone have any ideas? I really should have included the explanation of the problem at the top of the post, it is at the bottom :)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 04, 2005 7:43 am 
Beginner
Beginner

Joined: Mon Mar 14, 2005 4:16 pm
Posts: 27
I have the same problem :-(. I have created a User-UserGroup structure with many-to-many, and, for instance, if there are 5 rows in the association table, I get five results when I query for Users or for UserGroups, some of them duplicated. I have a structure like this one:

Code:
Users
-------
1  John
2  Peter

UserGroups
---------------
1  Admin
2  NormalUser

User_UserGroups (association table)
---------------------------------------------
User_id   UserGroup_id
1              1
1              2
2              2


If I do a query for users, I get:
John
John
Peter

(John appears twice)...

This only happens when using EAGER fetch mode...

Any help will be appreciated,

Bruno


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 04, 2005 7:48 am 
Beginner
Beginner

Joined: Mon Mar 14, 2005 4:16 pm
Posts: 27
Well... reading the posts again I see it's not the same problem... but at least it has to do with many-to-many and anotations... :-P

Thanks,

Bruno


Top
 Profile  
 
 Post subject: Re: many-to-many lazy fetching returning 'blank' objects
PostPosted: Tue Apr 05, 2005 1:22 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
shaldane wrote:
Is there something I am not doing right here to do with lazy initialization?

Check that you don't have anything final (method/class) in your classes

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 05, 2005 1:24 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
elmosca wrote:
This only happens when using EAGER fetch mode...

Any help will be appreciated,

Bruno

This is because Hibernate use a SQL join and get duplicates elements.
Wrap the results into a Set to distinct them

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 05, 2005 3:23 pm 
Beginner
Beginner

Joined: Mon Mar 14, 2005 4:16 pm
Posts: 27
Thanks emmanuel,

This was the conclusion I reached and this is how I am doing this now,

Congratulations for your wonderful work!

Bruno


Top
 Profile  
 
 Post subject: Re: many-to-many lazy fetching returning 'blank' objects
PostPosted: Tue Apr 05, 2005 7:43 pm 
Newbie

Joined: Tue Mar 29, 2005 1:52 am
Posts: 5
Location: Melbourne, Australia
emmanuel wrote:
Check that you don't have anything final (method/class) in your classes


That was it. I had gotten into the habit of making non-abstract methods final. It would be good if Hibernate logged a warning if it can't create the proxy classes because of final methods.

Thanks for your help Emmanuel. Keep up the good work.

Cheers,

Sam


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 06, 2005 4:28 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
I think it does already in the initialization phase

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 06, 2005 7:17 pm 
Newbie

Joined: Tue Mar 29, 2005 1:52 am
Posts: 5
Location: Melbourne, Australia
emmanuel wrote:
I think it does already in the initialization phase


It does if the class is final (see below) but not if getters / setters are final, which is what was causing the behaviour that was puzzling me.


Code:
2005-04-07 09:13:53,339 ERROR [main] hibernate.proxy.BasicLazyInitializer - CGLIB Enhancement failed: edu.acer.model.Customer
java.lang.IllegalArgumentException: Cannot subclass final class class edu.acer.model.Customer
   at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:438)
   at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
   at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:215)
   at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:368)
   at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:280)
   at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:597)
   at org.hibernate.proxy.CGLIBLazyInitializer.getProxyFactory(CGLIBLazyInitializer.java:94)
   at org.hibernate.proxy.CGLIBProxyFactory.postInstantiate(CGLIBProxyFactory.java:42)
   at org.hibernate.tuple.PojoTuplizer.buildProxyFactory(PojoTuplizer.java:139)
   at org.hibernate.tuple.AbstractTuplizer.<init>(AbstractTuplizer.java:83)
   at org.hibernate.tuple.PojoTuplizer.<init>(PojoTuplizer.java:54)
   at org.hibernate.tuple.TuplizerLookup.create(TuplizerLookup.java:47)
   at org.hibernate.tuple.EntityMetamodel.<init>(EntityMetamodel.java:212)
   at org.hibernate.persister.entity.BasicEntityPersister.<init>(BasicEntityPersister.java:400)
   at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:104)
   at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:55)
   at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:199)
   at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1054)
   at edu.acer.persistence.HibernateUtil.openSession(HibernateUtil.java:212)
   at edu.acer.persistence.HibernateUtil.openSession(HibernateUtil.java:128)
   at edu.acer.persistence.PersistentObject.store(PersistentObject.java:39)
   at edu.acer.Blah.main(Blah.java:30)
2005-04-07 09:13:53,339  WARN [main] hibernate.tuple.PojoTuplizer - could not create proxy factory for:edu.acer.model.Customer
org.hibernate.HibernateException: CGLIB Enhancement failed: edu.acer.model.Customer
   at org.hibernate.proxy.CGLIBLazyInitializer.getProxyFactory(CGLIBLazyInitializer.java:108)
   at org.hibernate.proxy.CGLIBProxyFactory.postInstantiate(CGLIBProxyFactory.java:42)
   at org.hibernate.tuple.PojoTuplizer.buildProxyFactory(PojoTuplizer.java:139)
   at org.hibernate.tuple.AbstractTuplizer.<init>(AbstractTuplizer.java:83)
   at org.hibernate.tuple.PojoTuplizer.<init>(PojoTuplizer.java:54)
   at org.hibernate.tuple.TuplizerLookup.create(TuplizerLookup.java:47)
   at org.hibernate.tuple.EntityMetamodel.<init>(EntityMetamodel.java:212)
   at org.hibernate.persister.entity.BasicEntityPersister.<init>(BasicEntityPersister.java:400)
   at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:104)
   at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:55)
   at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:199)
   at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1054)
   at edu.acer.persistence.HibernateUtil.openSession(HibernateUtil.java:212)
   at edu.acer.persistence.HibernateUtil.openSession(HibernateUtil.java:128)
   at edu.acer.persistence.PersistentObject.store(PersistentObject.java:39)
   at edu.acer.Blah.main(Blah.java:30)
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class edu.acer.model.Customer
   at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:438)
   at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
   at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:215)
   at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:368)
   at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:280)
   at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:597)
   at org.hibernate.proxy.CGLIBLazyInitializer.getProxyFactory(CGLIBLazyInitializer.java:94)
   ... 15 more


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 07, 2005 10:43 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Please post that to JIRa as an enhancement

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 07, 2005 5:47 pm 
Regular
Regular

Joined: Tue Jan 06, 2004 3:32 pm
Posts: 80
Location: Munich, Germany
If I were you, I would not post that to JIRA. Gavin might get upset about this.

I had the exact same problem some days ago (http://forum.hibernate.org/viewtopic.php?t=940690)

Instead of giving a hint about what I was doing wrong, he answered my question if I should post a bug report to JIRA just with:

"Of course you should not. This is incredibly well-documented."

Regards,

Andreas


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 07, 2005 7:43 pm 
Newbie

Joined: Tue Mar 29, 2005 1:52 am
Posts: 5
Location: Melbourne, Australia
I don't believe that it is well documented that accessors and mutators should not be declared final. As you said in the other thread, I would expect it to be mentioned in section 4.1.1 of the manual.

I think improving the manual and also logging a warning (or error) if accessors / mutators of persistent fields are final would be very helpful to people starting out with Hibernate.

I will post it to JIRA as an enhancement.


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