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.  [ 7 posts ] 
Author Message
 Post subject: StackOverflowError when loading non-hierarchical object
PostPosted: Wed Mar 05, 2008 2:31 pm 
Newbie

Joined: Wed Jan 16, 2008 8:23 am
Posts: 7
Hi,

I get a StackOverflowError when trying to load an object - Hibernate seems to get into an infinite recursion even though I have no hierarchical mappings set up. Basically what I'm trying to do is set up a many-to-many mapping that has the following characteristics:
- the join table has extra fields besides the two foreign keys
- one of the join table's foreign keys is part of its primary key (it's a legacy database ;)

As far as I understand this cannot be done using the @JoinTable annotation, you have to define a separate entity for the join table. Also, because you cannot simply make a foreign key also a primary key (at least Hibernate doesn't seem to support this), I need to define a different entity for the composite primary key, and import it into the join table's entity using @EmbeddedId.

I can save a new company, and the contents of the join table get saved correctly too (the save operation is cascaded). However, if I try to load a company using session.get(class, id), Hibernate begins an infinite recursion, querying the company object again and again, until this results in a StackOverflowException.

Does anybody have any idea what could be wrong? All my other mappings work correctly, but I simply cannot get this one working.

Hibernate version:
Core: 3.2.6
Annotations: 3.3.0

Mapping documents:

Code:
@Entity
@Table(name = "companies")
public class Company {

   private Set<CompanyIndustry> companyIndustries;

   // ... other properties

   @OneToMany(mappedBy = "id.company", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
   public Set<CompanyIndustry> getCompanyIndustries() {
      return companyIndustries;
   }

   public void setCompanyIndustries(Set<CompanyIndustry> companyIndustries) {
      this.companyIndustries = companyIndustries;
   }


   // ... other getters/setters
}


// The join table
@Entity
@Table(name = "companies_to_industries")
public class CompanyIndustry {

   @EmbeddedId
   private CompanyIndustryId id;

   @ManyToOne
   @JoinColumn(name = "industryId")
   private Industry industry;

   public CompanyIndustryId getId() {
      return id;
   }

   public void setId(CompanyIndustryId id) {
      this.id = id;
   }


   public Industry getIndustry() {
      return industry;
   }

   public void setIndustry(Industry industry) {
      this.industry = industry;
   }

}


// The composite primary key for the join table
@Embeddable
public class CompanyIndustryId implements Serializable {

   private static final long serialVersionUID = 1L;

   @ManyToOne
   @JoinColumn(name = "companyId")
   private Company company;

   private String provider;

   public Company getCompany() {
      return company;
   }

   public void setCompany(Company company) {
      this.company = company;
   }

   public String getProvider() {
      return provider;
   }
   
   public void setProvider(String provider) {
      this.provider = provider;
   }

}



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

Code:
new HibernateTemplate(sessionFactory).executeAndTransformExceptions(new HibernateCallback() {

         public Object doInHibernate(Session session) throws HibernateException, SQLException {
            return session.get(Company.class, id);
         }
      });


Full stack trace of any exception that occurs:

java.lang.StackOverflowError
at java.lang.AbstractStringBuilder.delete(AbstractStringBuilder.java:700)
at java.lang.StringBuffer.delete(StringBuffer.java:374)
at oracle.jdbc.driver.OracleSql.parse(OracleSql.java:1029)
at oracle.jdbc.driver.OracleSql.getSql(OracleSql.java:312)
at oracle.jdbc.driver.OracleSql.getSqlBytes(OracleSql.java:591)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:202)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:810)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1039)
at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:850)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1134)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3339)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3384)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:186)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1787)
at org.hibernate.loader.Loader.doQuery(Loader.java:674)
(and then the following block gets repeated an "infinite" amount of times)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1860)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42)
at org.hibernate.loader.entity.BatchingEntityLoader.load(BatchingEntityLoader.java:82)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3049)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:399)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:375)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:195)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:846)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:557)
at org.hibernate.type.EntityType.resolve(EntityType.java:379)
at org.hibernate.type.ComponentType.resolve(ComponentType.java:584)
at org.hibernate.type.ComponentType.nullSafeGet(ComponentType.java:275)
at org.hibernate.loader.Loader.getKeyFromResultSet(Loader.java:1097)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:565)
at org.hibernate.loader.Loader.doQuery(Loader.java:701)
(repeated block ends)


Name and version of the database you are using:

Oracle 10g.

Debug level Hibernate log excerpt:

This is what gets displayed before each company query:
2008-03-05 18:21:07,680 [RMI TCP Connection(5)-192.168.34.199] DEBUG org.hibernate.jdbc.AbstractBatcher - preparing statement
2008-03-05 18:21:07,680 [RMI TCP Connection(5)-192.168.34.199] DEBUG org.hibernate.type.LongType - binding '1' to parameter: 1
2008-03-05 18:21:07,711 [RMI TCP Connection(5)-192.168.34.199] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 1, globally: 1)
2008-03-05 18:21:07,711 [RMI TCP Connection(5)-192.168.34.199] DEBUG org.hibernate.loader.Loader - processing result set
2008-03-05 18:21:07,711 [RMI TCP Connection(5)-192.168.34.199] DEBUG org.hibernate.loader.Loader - result set row: 0
2008-03-05 18:21:07,711 [RMI TCP Connection(5)-192.168.34.199] DEBUG org.hibernate.event.def.DefaultLoadEventListener - loading entity: [mypackage.Company#1]
2008-03-05 18:21:07,711 [RMI TCP Connection(5)-192.168.34.199] DEBUG org.hibernate.event.def.DefaultLoadEventListener - attempting to resolve: [mypackage.Company#1]
2008-03-05 18:21:07,711 [RMI TCP Connection(5)-192.168.34.199] DEBUG org.hibernate.event.def.DefaultLoadEventListener - object not resolved in any cache: [mypackage.Company#1]
2008-03-05 18:21:07,711 [RMI TCP Connection(5)-192.168.34.199] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Fetching entity: [mypackage.Company#1]
2008-03-05 18:21:07,711 [RMI TCP Connection(5)-192.168.34.199] DEBUG org.hibernate.loader.Loader - loading entity: [mypackage.Company#1]
2008-03-05 18:21:07,711 [RMI TCP Connection(5)-192.168.34.199] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 2, globally: 2)
2008-03-05 18:21:07,711 [RMI TCP Connection(5)-192.168.34.199] DEBUG org.hibernate.SQL -

Thanks,
Peter


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 07, 2008 3:19 pm 
Newbie

Joined: Mon Apr 07, 2008 2:00 pm
Posts: 3
I am seeing the same StackOverflowError mapping a OneToMany (and the associated ManyToOne) using an EmbeddedId. I tried several configs including explicitly defining the join columns, but no luck.

The association works fine when lazy loaded, but when I specify an EAGER FetchType, it throws the StackOverflowError.

It seems like it is encountering an infinite loop when it tries to fetch the children. But because the child's EmbeddedId references the parent, it tries to fetch the parent... which causes an infinite loop when it then tries to fetch the children.

I am working around the issue by using lazy loading, and retrieving the collection manually w/ an active session.

Li


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 07, 2008 3:47 pm 
Newbie

Joined: Mon Apr 07, 2008 2:00 pm
Posts: 3
I believe this is a known, open issue with Hibernate 3.2. Here's the Hibernate bug I found:

http://opensource.atlassian.com/projects/hibernate/browse/HHH-2277

Note that this is a fix for EJB-225: "Eager Bidirectional association with @ManyToOne in PK lead to infinite loop" ... which sounds more like what we're encountering.

In the comments, Steve points to some additional "workarounds"...

Li


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 05, 2009 2:55 pm 
Newbie

Joined: Fri Jan 02, 2009 8:21 pm
Posts: 9
I'm running into this as well. The bug log says that this only happens when the composite key is not embedded - however, I am using an embedded composite key and getting the same error.

I tried one of the suggested workarounds - using IdClass instead of an EmbeddedId. This doesn't work either - if I annotate the ManyToOne in the main class, I get an index out of bounds exception on the query. If I annotate it in the primary key class, I get the infinite loop again.


Top
 Profile  
 
 Post subject: Re: StackOverflowError when loading non-hierarchical object
PostPosted: Mon Jul 06, 2009 7:21 am 
Newbie

Joined: Mon Mar 13, 2006 9:15 am
Posts: 4
Location: Oslo Norway
I've also run into this infinite loop problem. The solution which worked in the end was:
* @IdClass
* Annotate only @Id in the "main" class
* Do your @ManyToOne in the Pk class, and make fetchType=LAZY
* Make the fetchType=LAZY in the @OneToMany

_________________
Ole Christian


Top
 Profile  
 
 Post subject: Re: StackOverflowError when loading non-hierarchical object
PostPosted: Thu Feb 25, 2010 10:54 am 
Newbie

Joined: Thu Feb 25, 2010 10:50 am
Posts: 1
Thank you very much Ole.

I struggled with this pair of issues (either invalid column index or stack overflow) for several days. Your suggestion has worked for me.


Top
 Profile  
 
 Post subject: Re: StackOverflowError when loading non-hierarchical object
PostPosted: Tue Mar 09, 2010 4:37 am 
Newbie

Joined: Tue Mar 09, 2010 4:17 am
Posts: 1
hello guys,
i came into this error as well and ole's solution worked for me too...thank you very much!
however, going on with the execution, i keep on receiving this exception, when trying to execute the ".persist" method through the entity manager:
javax.ejb.EJBException: javax.persistence.PersistenceException: org.hibernate.exception.DataException: could not insert: [com.caos.entities.Request]

and eclipse console says:
09:26:28,883 WARN [JDBCExceptionReporter] SQL Error: 0, SQLState: 22001
09:26:28,884 ERROR [JDBCExceptionReporter] Data truncation: Data too long for column 'route' at row 1
09:26:28,898 INFO [STDOUT] SendRequestServlet.java: Ready to send the request

i've been looking for the solution on the internet and i came up with the conclusion that it is a many-to-many unidirectional mapping issue again...can anyone confirm this and perhaps give a hint?


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