-->
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.  [ 6 posts ] 
Author Message
 Post subject: Problem with fetchType=eager and onetomany
PostPosted: Sun Feb 01, 2009 12:54 pm 
Newbie

Joined: Sun Feb 01, 2009 12:39 pm
Posts: 5
Hi,

I'm using Spring together with hibernate, I configure my hibernate setting with annotations. Now I have the following (simplified) table structure

report 1 : n reportColumn

In the report class I have a List with Column items, which are bound through a onetomany annotations:

Code:
@OneToMany(mappedBy="report", fetch=FetchType.EAGER)
   @Cascade({org.hibernate.annotations.CascadeType.ALL,
          org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
   @OrderBy(clause = "column_order_nr asc")
   private List<ReportColumn> columns = new ArrayList<ReportColumn>();


In the column class, I have a reference to the report class, configured with a manytoone annotation:

Code:
@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
   @JoinColumn(name="report_column_report_id")
   private Report report;


When I try to load all reports in my dao, there are too much report items returned:

Code:
public ArrayList<Report> getReports() {
      ArrayList<Report> reports =
         (ArrayList<Report>)this.getHibernateTemplate().loadAll(Report.class);
      return reports;
   }


The loadAll-method returns a report for each column. E.g. when I have a report with two columns, the loadAll-method returns the same report twice.

I already tried to avoid this by removing the FetchType.EAGER setting. Than the loadAll-method returns the expected number of reports. But when I save a selected report in a session bean and than try to access the columns of the report in another request, the following error occures:

Quote:
org.hibernate.LazyInitializationException - failed to lazily initialize a collection of role: de.dyspepsie.fode.doc.Report.columns, no session or session was closed


I already use the org.springframework.orm.hibernate3.support.OpenSessionInViewFilter provided by spring, but this keeps the session opened only for one request...

Do you have an idea how to handle this?

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 01, 2009 2:19 pm 
Senior
Senior

Joined: Thu Jan 08, 2009 3:48 pm
Posts: 168
Seems that HibernateTemplate tries to outsmart the user there, if you turn on the SQL Output i guess it includes columns with a left join.
Doing this usually requires either select DISTINCT or casting the result-list to a set in order to remove duplicates.

The LazyInitializationException is understandable, OSIV does one Session for the first Request, then your objects become detached.
To use them in a further request you have to reload or merge them back into the (new) session.

suggestions:
- only use the eager loading if you always need columns, including them when loading can otherwise be be easily accomplished (e.g. join fetch in HQL)
- unless you have a case where you access a column without knowing the report and want the report loaded remove the eager loading from the column side
- With HibernateTemplate.getSession() you can get access to the Session itself and use it to do HQL or Criteria Queries.
In your case i would suggest something along the lines of:
Code:
Session session = getHibernateTemplate().getSession();
List<Report> reports = (List<Report>)session.createQuery("select distinct r from reports r left join fetch r.columns").list();


Hope that helps, rating appreciated


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 01, 2009 3:28 pm 
Newbie

Joined: Sun Feb 01, 2009 12:39 pm
Posts: 5
Hi pkleindl,

thanks for your answer. The solution you posted worked for me, although I think that it shouldn't be necessary to make a left join when there's a oneToMany-decleration.
Nevertheless, I tried your solution and it worked for the problem I had, whereby a new problem occured now.

There's another table which has a relation to the report table:

report 1 : n reportRow

Up to now I didn't read the reportRow-table in another request than the report-table. Now I needed to do that and therefore I added the fetch=fetchType.EAGER attribute to the decleration:

Code:
@OneToMany(mappedBy="report", fetch=FetchType.EAGER)
@Cascade((org.hibernate.anotations.CascadeType.ALL,
                 org.hibernate.anotations.CascadeType.DELETE_ORPHAN))
private List<ReportRow> rows = new ArrayList<ReportRow>();


Now I receive the following error:


Quote:
org.hibernate.HibernateException: cannot simultaneously fetch multiple bags


Does anybody know how to avoid this error?

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 01, 2009 4:49 pm 
Senior
Senior

Joined: Thu Jan 08, 2009 3:48 pm
Posts: 168
Hi

The point is: HQL ignores the mapping, you have to define what you want in the statement

for your other problem map your collections with
Code:
@org.hibernate.annotations.Fetch(org.hibernate.annotations.FetchMode.SUBSELECT)

drop the left join fetch and the distinct and it should work fine


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 02, 2009 1:24 am 
Newbie

Joined: Sun Feb 01, 2009 12:39 pm
Posts: 5
Hi pkleindl,

thanks again, now it works as expected.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 02, 2009 4:28 am 
Expert
Expert

Joined: Thu Jan 08, 2009 6:16 am
Posts: 661
Location: Germany
If you want to fetch both lists eagerly you could also add @IndexColumn, as hibernate supports "real" lists.

_________________
-----------------
Need advanced help? http://www.viada.eu


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