-->
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: Collection of primitive types
PostPosted: Sun Feb 08, 2009 11:19 pm 
Newbie

Joined: Sun Feb 08, 2009 11:00 pm
Posts: 3
I'm new to Hibernate, and am using it in a GWT environment.
I've got a class Article which has a field Category_Ids which is a collection of Integers:
Code:
Set<Integer> category_ids = new HashSet<Integer>();


I've got a postgres database with a table category_article (category_id integer, article_id integer)

My Article.hbm.xml file contains the following mapping:


Code:
<class name="....Article" table="article"
      schema="public" lazy="false">
      <id name="uid" type="int">
         <column name="uid" />
         <generator class="native" />
      </id>
....
....
      <set name="category_Ids" table="category_article"
         lazy="false">
         <key column="Article_Id" />
         <element column="Category_Id" type="int" />
      </set>
</class>


1 problem, 1 question:
Problem: When attempting to load an Article, I an error that boils down to "Caused by: org.postgresql.util.PSQLException: ERROR: column category_i0_.article_id does not exist"
Articles load fine when I don't map the category_Ids property.

Question: Once I get this problem solved, how can I query the Articles to find all Articles where the Category_Ids set contains a given element? In straight SQL "SELECT Article.Id FROM Articles INNER JOIN category_article on Article.Id = category_article.article_id WHERE category_article.category_id = ?"

I'm tearing the little hair I have left trying to understand this and get it working. Any help would be appreciated.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 09, 2009 3:05 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Quote:
Once I get this problem solved, how can I query the Articles to find all Articles where the Category_Ids set contains a given element?


Map the objects, not just the ID's. Here is an example http://www.hibernate.org/hib_docs/v3/re ... l-join-m2m

I also recommend setting lazy="true".

In your case, something like:
Code:
<set name="categories" table="category_article" lazy="true">
   <key column="Article_Id" />
   <many-to-many column="Category_Id"
            class="...Category"/>
</set>


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 09, 2009 7:01 am 
Expert
Expert

Joined: Fri Jan 30, 2009 1:47 am
Posts: 292
Location: Bangalore, India
Quote:
I also recommend setting lazy="true".

If you opt for the lazy fetching then hibernate uses some proxy objects for wrapping your entity objects. Now GWt doesnot recognize these proxy object types and it will start throwing Serialization exceptions if you are returning these entities from RPC methods. So if you are using lazy fetching you ll have to go for some libraries which will handle these situations for you like hibernate4gwt.

_________________
Regards,
Litty Preeth


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 09, 2009 8:05 am 
Regular
Regular

Joined: Thu Sep 06, 2007 2:22 am
Posts: 108
Location: Noida,India
Hi n_none,

Try this query:

" SELECT art FROM Article as art INNER JOIN art.category_ids as cat WHERE cat =:catId";


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 09, 2009 10:46 am 
Newbie

Joined: Sun Feb 08, 2009 11:00 pm
Posts: 3
nordborg,
I'd rather not map the whole object, It gains me nothing in this particular case. The only thing I need is the Id for searching, and pulling the rest of the Category just adds weight to the objects. In addition, I have to avoid lazy loading because this is a GWT environment and the classes have to be serializable. In fact, I had to modify the setCategories(Set<Integer> ids) function to perform a copy of the passed in ids to avoid the PeristantHashSet that hibernate uses

Code:
public void setCategories(Set<Integer> categories)
    {
   this.categories.clear();
   this.categories.addAll(categories);
    }


Is there any way of doing it without fully mapping the Category class? What about the case where the collection is not of Ids, but a collection of, say, keywords or tags which don't relate to another class, how is this situation handled? I'd not trying to be confrontational, just trying to learn this stuff.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 09, 2009 2:43 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
I don't know anything of GWT and don't even know what it stands for. Google Web Toolkit? It was the first hit on Google.

If GWT prevents lazy loading I would say that it is not very useful together with Hibernate. If you are forced to map relations as plain integers there are a lot of Hibernate features you will not be able to use, such as joining things in queries, cascading, etc. The only workaround for this is to map ALL tables as entities, including the category_article table. Then you should be able to do something like:

Code:
SELECT a FROM Article a, CategoryArticle ca WHERE a.id=ca.article_id AND ca.category_id = ?


The 'setCategories' example you provide will probably also get you in trouble since Hibernate will detect this as a modification to the collection. The end result is that every transaction (if you commit it) will first delete and then re-insert all values for the collection.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2009 1:12 am 
Expert
Expert

Joined: Fri Jan 30, 2009 1:47 am
Posts: 292
Location: Bangalore, India
Yes GWT stands for Google Web Toolkit.

I never said "GWT prevents lazy loading". What I meant is there are some things you need to consider when you turn on lazy loading in hibernate GWT combo.

First of all problem is only with lazy="proxy" or lazy="no-proxy" for associations (There is no lazy="true" AFAIK). This doesnt mean that you are forced to map relations as plain integers. In relations you CAN map entities to foreign key columns. Its just that its easier if you opt lazy=false in those mappings to have eager fetching. Like:
Code:
<many-to-one name="parent" class="com.test.ParentBO"
      cascade="all" fetch="join" lazy="false" access="property">
    <column name="PAR_ID" sql-type="number"></column>
</many-to-one>

But if this gives a major hit to the performance of your system you can always go for lazy fetching. But in that case either:
    - you should not return from an RPC call the proxy objects with lazy associations directly. You should first get the actual entity object from the wrapper and then return it.
    - you should use a 3rd party lib like hibernate4gwt to convert those proxy objects

_________________
Regards,
Litty Preeth


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2009 1:14 am 
Regular
Regular

Joined: Thu Sep 06, 2007 2:22 am
Posts: 108
Location: Noida,India
Hi n_none,

Please try this query:

" SELECT art FROM Article as art INNER JOIN art.category_ids as cat WHERE cat =:catId";


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2009 3:18 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Quote:
There is no lazy="true" AFAIK


Yes there is. For collections you can have lazy="false", laze="true" or lazy="extra".

As for GWT, I have absolutely no knowledge of it, so I will not comment further on other issues with lazy loading, proxies, etc.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 10, 2009 7:47 pm 
Newbie

Joined: Sun Feb 08, 2009 11:00 pm
Posts: 3
I figured it out. There are two things that needed to be done.
1. .hbn.xml has to have the mapping:
Code:
<set name="category_Ids" inverse="false" table="article_category"
         lazy="false">
        <key column="article_id" />
   <element type="integer" column="category_id"/>
</set>

The key was the <element> tag. Guess I needed to do a little more reading.

2. GWT can't support the PersistentSet. So I had to create a parallel data transfer class which uses a HashSet instead of a PersistentSet, and copy the Article to the data transfer class which the client uses.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 12, 2009 5:20 pm 
Newbie

Joined: Fri May 11, 2007 10:54 am
Posts: 7
Hi,

Maybe you could have a look at Gilead library (http://gilead.sourceforge.net), previously known as hibernate4gwt, that allow you to seamlessly send Hibernate entities to GWT and get them back without effort.

Hope this helps !
Bruno


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.