-->
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: one-to-many mapping problem
PostPosted: Tue Oct 14, 2003 4:06 pm 
Newbie

Joined: Mon Sep 15, 2003 12:55 pm
Posts: 9
Location: Bangkok, Thailand
Hi

My xml files are

Code:
<hibernate-mapping>
    <class name="hibernate.Factory" table="factories">
        <id name="id" type="integer" column="factoryid">
            <generator class="native"/>
        </id>
        <property name="name" column="factoryname" type="string" not-null="true"/>
        <set name="products" inverse="true">
            <key column="factoryid"/>
            <one-to-many class="hibernate.Product"/>
        </set>
    </class>
</hibernate-mapping>


Code:
<hibernate-mapping>
    <class name="hibernate.Product" table="products">
        <id name="id" type="integer" column="productid">
            <generator class="native"/>
        </id>
        <property name="name" column="productname" type="string" not-null="true" />
        <many-to-one name="produceFactory" column="factoryid" not-null="true"
            insert="true" update="true"/>
    </class>
</hibernate-mapping>


And my code is

Code:
        Product pA = new Product();
        pA.setName("pa");

        Factory a = new Factory();
        a.setName("a");

        Set allProducts = new HashSet();
        allProducts.add(pA);

        a.setProducts(allProducts);

        Transaction tx = session.beginTransaction();
        try {
            session.save(a);
            tx.commit();
        } catch (HibernateException e) {
            e.printStackTrace();
            tx.rollback();
        } finally {
            session.close();
        }


When run it doesn't store Product pA into database. Please tell me why.

Best Regard


Top
 Profile  
 
 Post subject: set the parent on the child
PostPosted: Tue Oct 14, 2003 4:20 pm 
Senior
Senior

Joined: Sun Aug 31, 2003 3:14 pm
Posts: 151
Location: Earth (at the moment)
You have declared a bidirectional association.
Did you remember to set the parent on the child?
Because you have inverse="true" on the parent the child is responsible for updating the association, if you didn't set the parent reference on the child that isn't possible.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 14, 2003 4:41 pm 
Newbie

Joined: Mon Sep 15, 2003 12:55 pm
Posts: 9
Location: Bangkok, Thailand
I've change my code to

Code:
        Product pA = new Product();
        pA.setName("pa");

        Factory a = new Factory();
        a.setName("a");

        Set allProducts = new HashSet();
        allProducts.add(pA);

        a.setProducts(allProducts);
        pA.setProduceFactory(a);

        Transaction tx = session.beginTransaction();
        try {
            session.save(a);
            session.save(pA);
            tx.commit();
        } catch (HibernateException e) {
            e.printStackTrace();
            tx.rollback();
        } finally {
            session.close();
        }
    }


It's work but it's very inconvenient. How can I stord a collection of Products with just save the refference of Factory.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 14, 2003 5:57 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
paan wrote:
It's work but it's very inconvenient. How can I stord a collection of Products with just save the refference of Factory.

Just follow the bible. Have a look at 8.2 and 8.3 section of the reference guide.
The cascade="all" or cascade="save-update" is what you want.


Top
 Profile  
 
 Post subject: Convenience methods...
PostPosted: Tue Oct 14, 2003 6:29 pm 
Senior
Senior

Joined: Sun Aug 31, 2003 3:14 pm
Posts: 151
Location: Earth (at the moment)
Read the documentation again, it shows how to make setting the parent on the child transparent.

Just put the call to set the parent on the child inside the method where you add the child to the parent:
Code:
public void setProducts(Set products) {
   this.products = products;
   Iterator prodIterator = products.iterator();
   while (prodIterator.hasNext()) {
      ((Product)prodIterator.next()).setProduceFactory(this);
   }
}


An easier approach would be to make an "add" method on Factory and use it to add products instead of manually creating a new HashSet each time and setting it.

Your code could look like this then:
Code:
        Product pA = new Product();
        pA.setName("pa");

        Factory a = new Factory();
        a.setName("a");

        a.addProduct(pA);

        Transaction tx = session.beginTransaction();
        try {
            session.save(a);
            session.save(pA);
            tx.commit();
        } catch (HibernateException e) {
            e.printStackTrace();
            tx.rollback();
        } finally {
            session.close();
        }


You would then have something like this on Factory:
Code:
public void addProduct(Product product) {
   productsSet.add(product);
   product.setProduceFactory(this);
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 15, 2003 1:55 pm 
Newbie

Joined: Mon Sep 15, 2003 12:55 pm
Posts: 9
Location: Bangkok, Thailand
I've slow myself down a bit. I've try to map collection with unidirectional Associations. But it doesn't work either.

Code:
    <class name="hibernate.Factory" table="factories">
        <id name="id" type="integer" column="factoryid">
            <generator class="native"/>
        </id>
        <property name="name" column="factoryname" type="string" not-null="true"/>
        <set name="allProducts" lazy="true">
            <key column="factoryid"/>
            <one-to-many class="hibernate.Product"/>
        </set>
    </class>


Code:
    <class name="hibernate.Product" table="products">
        <id name="id" type="integer" column="productid">
            <generator class="native"/>
        </id>
        <property name="name" column="productname" type="string" not-null="true" />
    </class>


Code:
        Product product = new Product();
        product.setName("pa");

        Factory factory = new Factory();
        factory.setName("B");

        Set allProducts = new HashSet();
        allProducts.add(product);

        factory.setAllProducts(allProducts);

        Transaction tx = session.beginTransaction();
        try {
            session.save(factory);
            tx.commit();
        } catch (HibernateException e) {
            e.printStackTrace();
            tx.rollback();
        } finally {
            session.close();
        }


I generate following DDL wiht SchemaExport

Code:
drop table products
drop table factories
drop table people
create table products (
   productid INTEGER NOT NULL AUTO_INCREMENT,
   productname VARCHAR(255) not null,
   factoryid INTEGER,
   primary key (productid)
)
create table factories (
   factoryid INTEGER NOT NULL AUTO_INCREMENT,
   factoryname VARCHAR(255) not null,
   primary key (factoryid)
)
create table people (
   peopleid INTEGER NOT NULL AUTO_INCREMENT,
   name VARCHAR(255) not null,
   birthdate DATE not null,
   primary key (peopleid)
)
alter table products add index (factoryid), add constraint FKC42BD164B0E323A5 foreign key (factoryid) references factories (factoryid)


when excecute the exception occur
Code:
net.sf.hibernate.HibernateException: SQL update or deletion failed (row not found)
   at net.sf.hibernate.impl.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:25)
   at net.sf.hibernate.collection.CollectionPersister.recreate(CollectionPersister.java:633)
   at net.sf.hibernate.impl.ScheduledCollectionRecreate.execute(ScheduledCollectionRecreate.java:23)
   at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2100)
   at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2065)
   at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2005)
   at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:57)
   at hibernate.UseHibernate.main(UseHibernate.java:53)


Please enlight me.

Best Regard


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 15, 2003 3:03 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Code:
...
        <set name="allProducts" lazy="true" cascade="save-update">
            <key column="factoryid"/>
            <one-to-many class="hibernate.Product"/>
        </set>
    </class>

Add the cascade="save-update" attribute to the set tag.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 15, 2003 3:19 pm 
Newbie

Joined: Mon Sep 15, 2003 12:55 pm
Posts: 9
Location: Bangkok, Thailand
Quote:
Add the cascade="save-update" attribute to the set tag.


It still doesn't work but the exception has chanced to


Code:
net.sf.hibernate.HibernateException: SQL update or deletion failed (row not found)
   at net.sf.hibernate.impl.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:25)
   at net.sf.hibernate.persister.EntityPersister.update(EntityPersister.java:642)
   at net.sf.hibernate.persister.EntityPersister.update(EntityPersister.java:611)
   at net.sf.hibernate.impl.ScheduledUpdate.execute(ScheduledUpdate.java:31)
   at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2100)
   at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2062)
   at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2005)
   at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:57)
   at hibernate.UseHibernate.main(UseHibernate.java:53)


I 've try other cascade options and none of it is work.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 15, 2003 4:51 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Assuming the Product.id java attribute is a primitive type, you need to set the unsaved-value parameter to an appropriate value. This parameter helps hibernate to choose between insert or update when using saveOrUpdate().
Because of the cascade="save-update", the save(factory) call for saveOrUpdate(product).
The default unsaved-value is null (as an object) whitcy is unappropriate for primitive types.
Try to set usaved-value to 0
Code:
<class name="hibernate.Product" table="products">
        <id name="id" type="integer" column="productid" unsaved-value="0">
            <generator class="native"/>
        </id>


If the product.id = 0 then hibernate will insert it. If product.id != 0 then hibernate will update it.
I think your exception is raised because hibernate try to update a non existing value because unsaved-value is wrong.

Keep cascade="saved-update" and add the unsaved-value="0" (or an other appropriate value).

See the reference guide (section 4.1.4 and more) for better details.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 15, 2003 6:20 pm 
Newbie

Joined: Mon Sep 15, 2003 12:55 pm
Posts: 9
Location: Bangkok, Thailand
It's working. Thank you epbernard. I begin to understand the Hibernate mapping. I used to work with Apache OJB. It's very slow compare to hibernate. But it's very easy to map collection though.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 15, 2003 6:51 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
You'll see, it a bit hard to get into it, but very intuitive once you quite understand hibernate concepts.


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.