-->
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: many-to-one mapping problem
PostPosted: Sun Aug 03, 2008 10:39 pm 
Newbie

Joined: Sun Aug 03, 2008 10:32 pm
Posts: 4
Hello, I am using NHibernate 1.2 to construct a proof of concept project as well as a learning example. I have the following problem in my Domain Objects where.
Code:
public class Customer {
   public virtual int CustomerId;
}
public class CustomerAtSite : Customer {
   public virtual int CustomerAtSite;
   public virtual IList<AssignedProduct> Products;
}
public class Product {
   public virtual int ProductId;
}
public class AssignedProduct : Product {
   public virtual int AssignedProductId;
   public virtual CustomerAtSite Customer;
}

Where in the database you have the following tables:
CUSTOMER with pk CUSTOMER_ID
CUSTOMER_SITES with pk CUSTOMER_SITE_ID and fk CUSTOMER_ID
PRODUCT with pk PRODUCT_ID
CUST_PROD with pk CUST_PROD_ID and fk PROD_ID for inheritance, and fk CUSTOMER_SITE_ID for a one-to-many reference

In addition, I have the following hbms declared:
Customer.hbm.xml:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
    <class name="EDC2_Objects.Core.Domain.Customer, EDC2_Objects.Core" table="Customer" lazy="false">
        <id name="CustomerId" column="CUSTOMER_ID" type="Int32">
            <generator class="native" />
        </id>
        <joined-subclass name="EDC2_Objects.Core.Domain.CustomerAtSite, EDC2_Objects.Core" table="CUSTOMER_SITES">
            <key column="CUSTOMER_ID" />
            <property name="CustomerSiteId" column="CUSTOMER_SITE_ID" type="Int32" not-null="true" unique-key="true"/>
            <bag name="Products" lazy="true">
                <key column="CUSTOMER_SITE_ID" foreign-key="CustomerSiteId"/>
                <one-to-many class="EDC2_Objects.Core.Domain.AssignedProduct,  EDC2_Objects.Core" />
            </bag>
        </joined-subclass>
    </class>
</hibernate-mapping>

And, Product.hbm.xml:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
    <class name="EDC2_Objects.Core.Domain.Product, EDC2_Objects.Core" table="Product" lazy="false">
        <id name="ProductId" column="PROD_ID" type="Int32">
            <generator class="native" />
        </id>
        <property name="Name" column="NAME" type="String" length="50"  not-null="false"/>
        <joined-subclass name="EDC2_Objects.Core.Domain.AssignedProduct, EDC2_Objects.Core" table="CUST_PROD">
            <key column="PROD_ID" />
            <property name="CustomerProductId" column="CUST_PROD_ID" type="Int32" not-null="true" unique-key="true" />
            <many-to-one name="Customer" column="CUSTOMER_SITE_ID" not-null="true" class="EDC2_Objects.Core.Domain.CustomerAtSite, EDC2_Objects.Core"  property-ref="CustomerSiteId"/>
        </joined-subclass>
    </class>
</hibernate-mapping>


Finally, I am testing it with the following piece in MbUnit:
Code:
    [TestFixture]
    [FixtureCategory("Database")]
    public class CustomerAtSiteTests : NHibernateTestCase {
        [Test]
        public void CustomerHasProducts() {
            int cs_id = 54;
            int[] e_cp_id = {116, 120};

            IDaoFactory factory = new NHibernateDaoFactory();
            ICustomerAtSiteDao dao = factory.GetCustomerAtSiteDao();

            CustomerAtSite c = dao.GetById(cs_id);
            Assert.AreEqual(e_cp_id.Length, c.Products.Count);

            foreach (AssignedProduct p in c.Products) {
                CollectionAssert.Contains(e_cp_id, p.ProductId);
                Assert.AreEqual(c.CustomerSiteId, p.Customer.CustomerSiteId);
            }
        }
    }


The test fails, and examining the the NHibernate show_sql=true output, I see that that call to c.Products executes as:
Code:
SELECT products0_.CUSTOMER_SITE_ID AS CUSTOMER3___1_, products0_.PROD_ID AS PROD1_1_, products0_.PROD_ID AS PROD1_5_0_, products0_.CUST_PROD_ID AS CUST2_6_0_,
       products0_.CUSTOMER_SITE_ID AS CUSTOMER3_6_0_, products0_1_.NAME AS NAME5_0_
FROM   CUST_PROD products0_ INNER JOIN Product products0_1_ ON products0_.PROD_ID = products0_1_.PROD_ID
WHERE  products0_.CUSTOMER_SITE_ID =:p0; :p0 = '46'


The problem is visible immediately. 46 is the CUSTOMER_ID but p0 should be se to the value of CUSTOMER_SITE_ID (:p0=54);

Can anyone help correct my mapping?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 05, 2008 2:13 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
You can't do that at the moment:

http://jira.nhibernate.org/browse/NH-1272

Currently only the id can be used to map a collection.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 05, 2008 2:19 pm 
Newbie

Joined: Sun Aug 03, 2008 10:32 pm
Posts: 4
Thank you for the reply, is there some other way that I can approach this? I cannot change the database but I can change my object hierarchy.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2008 6:04 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
You can use the CustomerId instead of the CustomerSiteId to build the foreign key between the tables.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2008 9:45 am 
Newbie

Joined: Sun Aug 03, 2008 10:32 pm
Posts: 4
Like I said, I can change anything about the classes, but I am working with a legacy database so I cannot change that. To rehash I have the following tables:

SITE
CUSTOMER
CUSTOMER_SITES with a fk to CUSTOMER and SITE
PRODUCT
CUST_PROD with a fk to CUSTOMER_SITES and PRODUCT

The conceptual idea being that you can have a customer with some information and you can have a customer at a site (which comes with a whole lot more information then an unassigned customer). Similarly, you can have an unassigned product or you can have a product that is assigned to a customer/site combination.

Yes, I am aware that the fully normalized solution would be to have a table linking customer, product, and site but this is what they already have and frankly its not the worst setup in the universe. Is there any workaround that people use to model these sort of relationships in NHibernate?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 06, 2008 10:09 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
You can try and model your classes along the table design and use associations instead of inheritance.

CustomerAtSite <- 1:1 -> Customer
AssignedProduct <- 1:1 -> Product
CustomerAtSite <- 1:n -> AssignedProduct

There you can use the CustomerSiteId to joind the assigne products.

_________________
--Wolfgang


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.