-->
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.  [ 4 posts ] 
Author Message
 Post subject: Mapping association defined by (discriminator, FK) pair
PostPosted: Mon May 07, 2007 5:18 pm 
Beginner
Beginner

Joined: Wed Apr 18, 2007 1:44 pm
Posts: 27
Hi all,

Anyone knows if it's possible to map a combination of (discriminator,FK) that joins to different tables/entities depending on the discriminator value.

Notice that here discriminator has nothing to do with mapping hierarchies. It's a discriminator just in the sense that it distinguished between different join tables.

For example Review with (targetKind, targetId) where targetKind could be Product or Store. Then the review will have getTarget() -> Object and the Store and Product will both have getReviews() -> List<Review>.

This is a simple example. My actual situation is far more complex. Following is a list of obvious solutions that are nonos in my case:

1) Different table for each review. Example: ProductReview, StoreReview. Impossible because there are a lot of review targets, I have more feedback elements than plain reviews, some feedback elements are somewhat recursive in respect to other feedback elements, so the combination is even higher.

2) Multiple FKs for the review. As a review can have different types of targets (which are not all well known in advance aside from Product, Store and a handful more), a lot of nulled out columns would be wasted.

One solution could be having a ReviewList in between the target and the reviews. So you have a "one-to-one FK" from Product to ReviewList (but not the inverse) or, say, from Store to ReviewList. The associacion between ReviewList would then be one-to-many. The additional join can be trivially optimized out by the execution planner.

Anyway, this solution seems overcomplicated. The thing I would have done if not using an ORM is to simply define the aforementioned targetKind for Review. But I can't see a clean way to express an association on top of this (discriminator, FK) combination with hibernate.

Any help would be appreciated.

TIA.
Cheers,
Carlos


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 08, 2007 3:51 am 
Regular
Regular

Joined: Mon Mar 26, 2007 12:38 am
Posts: 119
Hi,
Here is one way of doing it. See, if it helps.
If you meant <discriminator> and polymorphic persistence, Kindly excuse. Reply may be irrelevant.
In the mean time, I'll try to come up with an example using discriminators. ( It's a learning. I have never used them )

Tables: ( stub )

1) Review: id , type ( 'STORE' / 'PRODUCT'), target_id, des
2) Product: id, name
3) Store: id, name


Mapping files.

1) Review.hbm.xml
<hibernate-mapping >
<class name="Review" table="review" >
<id name="id" column="id" type="integer"></id>
<property name="des" type="string" column="des"/>
<many-to-one class="Store" name="store" >
<formula>decode(type, 'STORE',target_id, null)</formula>
</many-to-one>
<many-to-one class="Product" name="product" >
<formula>decode(type, 'PRODUCT',target_id, null)</formula>
</many-to-one>
</class>
</hibernate-mapping>

2) Store.hbm.xml
<hibernate-mapping >
<class name="Store" table="store">
<id name="id" column="id" >
<generator class="increment" />
</id>
<property name="name" type="string" column="name"/>
<set name="reviews" >
<key column="target_id"/>
<one-to-many class="cars.models.Review"/>
<filter name="storeReviewFilter" condition=" type = 'STORE' "/>
</set>
</class>
<filter-def name="storeReviewFilter"/>
</hibernate-mapping>

3) Product.hbm.xml
<hibernate-mapping >
<class name="Product" table="product">
<id name="id" column="id" >
<generator class="increment" />
</id>
<property name="name" type="string" column="name"/>
<set name="reviews" >
<key column="target_id"/>
<one-to-many class="Review"/>
<filter name="productReviewFilter" condition=" type = 'PRODUCT' ">
</filter>
</set>
</class>
<filter-def name="productReviewFilter"/>
</hibernate-mapping>


Note:
i) I have used decode in <formula>, an Oracle function. Use an equivalent of the underlying database.
ii) Both Store and Product objects are available in Review. One of the two is always null and the other holds target. We can introduce getTarget() function which returns this Target. ( I am leaving it here... )
iii) enable the Session Filters.
session.enableFilter("storeReviewFilter") ;
session.enableFilter("productReviewFilter") ;

-----------------------------------------------------
Rate the reply if you find it helpful


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 09, 2007 4:26 pm 
Beginner
Beginner

Joined: Wed Apr 18, 2007 1:44 pm
Posts: 27
Hi,

thank you very much for your detailed answer.

I would like to remark that I'm using annotations. So I tried to "translate" your xml descriptors to java annotations.

I still can't get it working. Number one, which is just an annoyance, the auto generated schema for Review has columns for each target (I mean, productTarget_id, storeTarget_id, etc etc). Number two, if I hand-write the DDL, the generated INSERTs still look for different target columns. Number three, if I map each association to the same target_id join column, I get an error at session startup saying that a mapping is dupplicated.

Besides, I don't understand the use of formulas for associations at all. The documentation keeps silence about it and the Address example (chapter 23) doesn't enlight me:

<class name="Person">
<id name="name"/>
<one-to-one name="address"
cascade="all">
<formula>name</formula>
<formula>'HOME'</formula>
</one-to-one>
<one-to-one name="mailingAddress"
cascade="all">
<formula>name</formula>
<formula>'MAILING'</formula>
</one-to-one>
</class>

Why two <formula>, one after the other? What does this mean?

Thank you in advance
Cheers,
Carlos


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 10, 2007 12:09 am 
Regular
Regular

Joined: Mon Mar 26, 2007 12:38 am
Posts: 119
Hi,
>>> I'm using annotations. I still can't get it working.
The posting has mapping files picked up directly from a working program. ( which I had set to mimic the scenario ).
I don't use ( neither I know much about ) Hibernate annonations.

>>> I don't understand the use of formulas for associations at all. The documentation keeps silence about it and the Address example (chapter 23) doesn't enlight me.

I'll put some light into their use in associations.
A) One formula. ( Simple Id )
Formula can be used when we want some expressions to link to the other end instead of plain column. Let's take our example,
<many-to-one class="Store" name="store" >
<formula>decode(type, 'STORE',target_id, null)</formula> ( formula _1)
</many-to-one>
<many-to-one class="Product" name="product" >
<formula>decode(type, 'PRODUCT',target_id, null)</formula> ( formula_2 )
</many-to-one>


Further query to fetch Store and Product would then be,
from Store where id = formula_1 ;
from Product where id = formula_2 ;


If target_id = 25 and type = 'STORE', then, first formual evaluates to 25 and second to null. So, the association fetch queries become,
from Store where id = 25;
from Product where id = null ; ( We have realized the discrminator value )

B) two formula, back to back. ( Composite Id )
(Address Class )
<composite-id>
<key-many-to-one name="person" column="personName"/>
<key-property name="type" column="addressType"/>
</composite-id>
(Person Class)
<one-to-one name="address"
cascade="all">
<formula>name</formula> (formula_1)
<formula>'HOME'</formula> (formula_2)
</one-to-one>

Here, formula_1 maps to first key attribute, name.
formula_2 to second key attribute, addressType.
So,
Association fetching query is,
from Address where name = formula_1 and addressType = formula_2.

Note: You can use the tests from hibernate source distribution to get better understanding.

-----------------------------------------------------------
Rate the reply if you find it helpful


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