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: Exception mapping one-to-many with Assocation class
PostPosted: Thu Apr 20, 2006 2:21 pm 
Newbie

Joined: Tue Apr 18, 2006 3:05 pm
Posts: 9
I have 2 domain objects which each contain a Set to the other (representing a many-to-many association). I have an association class (and table) in the middle but cannot for the life of me get this to work. I've re-created my error with a simplified Category/Item model. Any help would be SUPER appreciated as I am still learning Hibernate. The Manning book and docs didn't help me. I don't think my Exception with the primary key ('id' attribute) has anything to do with my generator class b/c I can switch back and forth to sequence, assigned, and increment w/ the same error. I feel what I am missing is how the Association class is handled when creating new objects....thanks in advance.

Note: I am able to persist a Category OK if I comment out the line in my test case method: category.addItem(item);


Hibernate version: 3

Mapping documents:
Category.hbm.xml
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="com.Category" table="CATEGORY" dynamic-update="true" dynamic-insert="true">
    <id name="id" column="CATEGORY_ID">
         <generator class="sequence">
            <param name="sequence">SEQ_ADVISORY</param>
        </generator>
    </id>

    <version name="version" type="long" column="VERSION" unsaved-value="null"/>

    <property name="name" column="CATEGORY_NAME"/>

    <set name="items" inverse="false" cascade="all-delete-orphan" lazy="false">
      <key>
          <column name="CATEGORY_ID"/>
      </key>
      <one-to-many class="com.CategoryItem"/>
    </set>
  </class>
</hibernate-mapping>

__________________________
Item.hbm.xml
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
  <class name="com.Item" table="ITEM" >

    <id name="id" column="ITEM_ID">
        <generator class="sequence">
            <param name="sequence">SEQ_ADVISORY</param>
        </generator>
    </id>

    <version name="version" type="long" column="VERSION" unsaved-value="null"/>

    <property name="name" column="ITEM_NAME"/>
    <property name="description" column="ITEM_DESCRIPTION"/>

    <set name="categories" inverse="false" cascade="all-delete-orphan" lazy="false">
      <key>
          <column name="ITEM_ID"/>
      </key>
      <one-to-many class="com.CategoryItem"/>
    </set>

  </class>
</hibernate-mapping>

________________________
CategoryItem.hbm.xml
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
  <class name="com.CategoryItem" table="CATEGORY_ITEM" dynamic-update="true" dynamic-insert="true">

    <id name="id" column="CATEGORY_ITEM_ID">
        <generator class="sequence">
            <param name="sequence">SEQ_ADVISORY</param>
        </generator>
    </id>

     <many-to-one name="category" column="CATEGORY_ID"
      class="com.Category" outer-join="false"></many-to-one>

    <many-to-one name="item" column="ITEM_ID"
      class="com.Item" outer-join="false"></many-to-one>
  </class>
</hibernate-mapping>


____________________________________
Category.java
Code:
package com;
import java.util.Set;
import java.util.HashSet;

public class Category
{
    private String id, name;
    private Set items = new HashSet();
    private Long version;

    // getters and setters omitted

    public void addItem(Item item)
    {
        items.add(item);
        item.getCategories().add(this);
    }
}

_____________
Item.java
Code:
package com;

import java.util.Set;
import java.util.HashSet;

public class Item
{
    private String id;
    private String name;
    private String description;
    private Set categories = new HashSet();
    private Long version;

    //getters and setters omitted   

    public void addCategory(Category category)
    {
        categories.add(category);
        category.getItems().add(this);
    }
}

______________
CategoryItem.java
Code:
package com;

public class CategoryItem
{
    private String id;
    private Category category;
    private Item item;

    //getters and setters omitted
}


Code between sessionFactory.openSession() and session.close():
Category category = new Category();
category.setName("test1");
Item item = new Item();
item.setDescription("desc_test");
item.setName("test item");
category.addItem(item);

/* calls 'persist' on Hibernate session */
myService.createCategory(category);


Full stack trace of any exception that occurs:
org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of com.CategoryItem.id
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:119)
at org.hibernate.tuple.AbstractTuplizer.getIdentifier(AbstractTuplizer.java:103)
at org.hibernate.persister.entity.BasicEntityPersister.getIdentifier(BasicEntityPersister.java:2944)
at org.hibernate.persister.entity.BasicEntityPersister.isTransient(BasicEntityPersister.java:2705)
at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:181)
at org.hibernate.event.def.AbstractSaveEventListener.getEntityState(AbstractSaveEventListener.java:409)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:70)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:519)
at org.hibernate.engine.Cascades$8.cascade(Cascades.java:221)
at org.hibernate.engine.Cascades.cascadeAssociation(Cascades.java:771)
at org.hibernate.engine.Cascades.cascade(Cascades.java:720)
at org.hibernate.engine.Cascades.cascadeCollection(Cascades.java:895)
at org.hibernate.engine.Cascades.cascadeAssociation(Cascades.java:792)
at org.hibernate.engine.Cascades.cascade(Cascades.java:720)
at org.hibernate.engine.Cascades.cascade(Cascades.java:847)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:363)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:265)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:160)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:108)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:124)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:84)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:525)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:529)
at com.service.persistence.hibernate.HibernateService.persist(HibernateService.java:32)
... 47 more
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:105)

Name and version of the database you are using: Oracle 10g express


Top
 Profile  
 
 Post subject: Exception mapping one-to-many with Assocation class
PostPosted: Thu Apr 20, 2006 2:30 pm 
Newbie

Joined: Tue Apr 18, 2006 3:05 pm
Posts: 9
Sorry...here's my schema.

CREATE TABLE CATEGORY (
CATEGORY_ID VARCHAR2(30) NOT NULL,
CATEGORY_NAME VARCHAR2(30) NULL,
VERSION NUMBER(6) NULL
);


ALTER TABLE CATEGORY
ADD ( PRIMARY KEY (CATEGORY_ID) ) ;


CREATE TABLE CATEGORY_ITEM (
CATEGORY_ITEM_ID VARCHAR2(30) NOT NULL,
CATEGORY_ID VARCHAR2(30) NULL,
ITEM_ID VARCHAR2(30) NULL
);

ALTER TABLE CATEGORY_ITEM
ADD ( PRIMARY KEY (CATEGORY_ITEM_ID) ) ;


CREATE TABLE ITEM (
ITEM_ID VARCHAR2(30) NOT NULL,
ITEM_NAME VARCHAR2(30) NULL,
ITEM_DESC VARCHAR2(30) NULL,
VERSION NUMBER(6) NULL
);


ALTER TABLE ITEM
ADD ( PRIMARY KEY (ITEM_ID) ) ;


ALTER TABLE CATEGORY_ITEM
ADD ( FOREIGN KEY (ITEM_ID)
REFERENCES ITEM ) ;


ALTER TABLE CATEGORY_ITEM
ADD ( FOREIGN KEY (CATEGORY_ID)
REFERENCES CATEGORY ) ;


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 20, 2006 2:43 pm 
Regular
Regular

Joined: Wed Feb 22, 2006 11:28 am
Posts: 65
Location: Santiago, Chile
Hello friend:

At your <set> tag situated in 2 hibernate mappings files, set inverse="true" rather than inverse="false". I guess that will help you to solve your proble.

requests for comments.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 20, 2006 2:51 pm 
Newbie

Joined: Tue Apr 18, 2006 3:05 pm
Posts: 9
Since Category is the parent object I am persisting, Item.hbm.xml should have inverse="true" and Catagory be left as inverse="false".

I tried that and still received the same error. dang. Any other ideas? Thanks again.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 21, 2006 2:18 pm 
Newbie

Joined: Tue Apr 18, 2006 2:50 pm
Posts: 10
Based on the exception, java.lang.IllegalArgumentException: object is not an instance of declaring class, and looking at your mapping and class files, I'd say to focus on how instances of CategoryItem are geting created.

If I'm reading everything correctly, your Category mapping file is saying that the "items" attribute is a set that should have CategoryItem instances in it. Your Item mapping is saying that the "categories" attribute is a set that should have CategoryItem instances. However, your Category class is adding instances of Item to the items set, while Item is adding instances of Category to the categories set. I believe you need to be creating instances of CategoryItem and adding them to the sets.

I'm not quite sure which is incorrect - your mapping or your class files. As a quick test, you could change your classes to create instances of CategoryItem and add them to the set. My gut tells me something is wrong in the mapping, but I can't quite put my finger on it - sorry. I'll have to chew on this one a bit and will get back to you if I have any thoughts.

Good luck!

-Eric Trull


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 21, 2006 2:40 pm 
Newbie

Joined: Tue Apr 18, 2006 2:50 pm
Posts: 10
Yeah, I think I've convinced myself that the mapping is incorrect. Looking at http://www.hibernate.org/hib_docs/v3/reference/en/html_single/#collections-bidirectional the mapping example does not have the intermediate object, CategoryItem. Is there some other motivation for using an intermediate object that is not shown in your schema? I could see using CategoryItem if you have some other bit of information that is saved in the join table (CATEGORY_ITEM). If that is the case, then your java code needs to change to create instances of CategoryItem (along with populating the additional bit of information). Otherwise elimiate CategoryItem.

Thanks.

-Eric Trull


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 21, 2006 2:50 pm 
Expert
Expert

Joined: Thu Sep 22, 2005 10:29 am
Posts: 285
Location: Almassera/Valencia/Spain/EU/Earth/Solar system/Milky Way/Local Group/Virgo Supercluster
I think that this is what you want:
Code:
public class Category
{
   private Set<Item> items = new HashSet<Item>();
}

public class Item
{
   private Set categories<Category> = new HashSet<Category>();
}

BUT this is what you have done:
Code:
public class Category
{
   private Set<CategoryItem> items = new HashSet<CategoryItem>();
}

public class Item
{
   private Set categories<CategoryItem> = new HashSet<CategoryItem>();
}


Look Hibernate reference at
7.5.3. many to many


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 21, 2006 3:53 pm 
Expert
Expert

Joined: Thu Sep 22, 2005 10:29 am
Posts: 285
Location: Almassera/Valencia/Spain/EU/Earth/Solar system/Milky Way/Local Group/Virgo Supercluster
If you can't get rid of the surrogate key then try:
Category map
Code:
<idbag
   name="items"
   table="CATEGORY_ITEM”
   lazy="true"
   cascade="save-update"
>
   <collection-id type="long" column="CATEGORY_ITEM_ID">
      <generator class="sequence"/>
   </collection-id>
   <key column="CATEGORY_ID"/>
   <many-to-many class="Item" column="ITEM_ID"/>
</idbag>

Item map
Code:
<set
   name="categories"
   table="CATEGORY_ITEM"
   lazy="true"
   cascade="save-update"
   inverse="true"
>
   <key column="ITEM_ID"/>
   <many-to-many class="Category" column="CATEGORY_ID"/>
</set>

POJOS
Code:
public class Category
{
   private List<Item> items = new ArrayList<Item>();
}

public class Item
{
   private Set categories<Category> = new HashSet<Category>();
}


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 24, 2006 4:09 pm 
Newbie

Joined: Tue Apr 18, 2006 3:05 pm
Posts: 9
pepelnm,
thanks for your responses, but I'm using jdk 1.4 and got several cglib errors when I tried your suggestion. I'm trying with an intermediate class now, but still running into issues. I'll post a solution for future searches (or another question if I can't get through these errors!).

thanks again.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 24, 2006 4:44 pm 
Newbie

Joined: Tue Apr 18, 2006 3:05 pm
Posts: 9
OK, I'm trying to make this work with an association class but still getting an error. I question my mappings due to the FK errors I am getting. Thanks in advance for all your help. It really is appreciated....I know I'm close.

Category.hbm.xml.....
Code:
<hibernate-mapping>
  <class name="com.Category" table="CATEGORY" dynamic-update="true" dynamic-insert="true">

    <id name="id" column="CATEGORY_ID">
         <generator class="sequence">
            <param name="sequence">SEQ_ADVISORY</param>
        </generator>
    </id>

    <version name="version" type="long" column="VERSION" unsaved-value="null"/>

    <property name="name" column="CATEGORY_NAME"/>

    <set name="categoryItems" inverse="false" cascade="all-delete-orphan" lazy="false">
      <key>
          <column name="ITEM_ID"/>
      </key>
      <one-to-many class="com.CategoryItem"/>
    </set>
  </class>

</hibernate-mapping>

-----------
CategoryItem.hmb.xml
Code:
<hibernate-mapping>
  <class name="com.CategoryItem" table="CATEGORY_ITEM" dynamic-update="true" dynamic-insert="true">

    <id name="id" column="CATEGORY_ITEM_ID">
        <generator class="sequence">
            <param name="sequence">SEQ_ADVISORY</param>
        </generator>
    </id>

     <many-to-one name="category" column="CATEGORY_ID" cascade="all-delete-orphan"
      class="com.Category" outer-join="false"></many-to-one>

    <many-to-one name="item" column="ITEM_ID" cascade="all-delete-orphan"
      class="com.Item" outer-join="false"></many-to-one>

  </class>
</hibernate-mapping>

--------------------
Item.hbm.xml
Code:
<hibernate-mapping>
  <class name="com.Item" table="ITEM" >

    <id name="id" column="ITEM_ID">
        <generator class="sequence">
            <param name="sequence">SEQ_ADVISORY</param>
        </generator>
    </id>

    <version name="version" type="long" column="VERSION" unsaved-value="null"/>

    <property name="name" column="ITEM_NAME"/>
    <property name="description" column="ITEM_DESC"/>

    <set name="categoryItems" inverse="true" cascade="all-delete-orphan" lazy="false">
      <key>
          <column name="CATEGORY_ID"/>
      </key>
      <one-to-many class="com.CategoryItem"/>
    </set>

  </class>
</hibernate-mapping>

************************
Catgory.java
Code:
public class Category
{
    private String id, name;
    private Set categoryItems = new HashSet();
    private Long version;

    public void addItem(Item item)
    {
        CategoryItem catItem = new CategoryItem(this, item);
        this.categoryItems.add(catItem);
        item.getCategoryItems().add(catItem);
    }

------CategoryItem.java
Code:
public class CategoryItem
{
    private String id;
    private Category category;
    private Item item;

    public CategoryItem()
    {
    }

    public CategoryItem(Category category, Item item)
    {
        this.category = category;
        this.item = item;
    }

}

--------------
Item.java
Code:
public class Item
{
    private String id;
    private String name;
    private String description;
    private Set categoryItems = new HashSet();
    private Long version;

}



ERROR:
Hibernate: select SEQ_ADVISORY.nextval from dual
Hibernate: select SEQ_ADVISORY.nextval from dual
Hibernate: select SEQ_ADVISORY.nextval from dual
Hibernate: insert into CATEGORY (VERSION, CATEGORY_NAME, CATEGORY_ID) values (?, ?, ?)
Hibernate: insert into ITEM (VERSION, ITEM_NAME, ITEM_DESC, ITEM_ID) values (?, ?, ?, ?)
Hibernate: insert into CATEGORY_ITEM (CATEGORY_ID, ITEM_ID, CATEGORY_ITEM_ID) values (?, ?, ?)
Hibernate: update CATEGORY_ITEM set ITEM_ID=? where CATEGORY_ITEM_ID=?

org.springframework.orm.hibernate3.HibernateJdbcException: JDBC exception on Hibernate data access: Could not execute JDBC batch update; nested exception is java.sql.BatchUpdateException: ORA-02291: integrity constraint (DB.CATEGORY_ITEM_FK) violated - parent key not found

java.sql.BatchUpdateException: ORA-02291: integrity constraint (CESSOAI1.CATEGORY_ITEM_FK) violated - parent key not found

at oracle.jdbc.dbaccess.DBError.throwBatchUpdateException(DBError.java:460)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:4133)
at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:294)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:57)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:174)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:226)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)
at org.springframework.orm.hibernate3.SessionFactoryUtils$SpringSessionSynchronization.beforeCommit(SessionFactoryUtils.java:869)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:564)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:424)
at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(TransactionAspectSupport.java:258)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:67)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:174)
at $Proxy3.addCategory(Unknown Source)
at com.ecarey.ces.service.advisory.AdvisoryServiceTestCase.testCategoryItemManyToManyJoin(AdvisoryServiceTestCase.java:52)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)


[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 25, 2006 10:43 am 
Regular
Regular

Joined: Fri Sep 09, 2005 11:35 am
Posts: 101
in your mappings for category item set in category change the key column to CATEGORY_ID instead of ITEM_ID

also the key column in category item mapping in item class also neeeds to be changed to ITEM_ID instead of CATEGORY_ID.


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.