-->
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.  [ 7 posts ] 
Author Message
 Post subject: @EmbeddableSuperclass and Tree structure (@OneToMany)
PostPosted: Mon Jan 23, 2006 12:11 pm 
Newbie

Joined: Sat Jan 07, 2006 5:18 pm
Posts: 19
Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp

Hibernate version: 3.1

Mapping documents: Annotations

Debug level Hibernate log excerpt:

I am having problems defining an @EmbeddableSuperclass relationship. In my domain model, I have objects that implement a tree structure, i.e. they each have a parent node and a list of children nodes, all of the same type. I though that I'd extract the common functionality such as the parent and child properties and some utility methods into a superclass.

Code:
@EmbeddableSuperclass(access = AccessType.PROPERTY)
public abstract class DAFEntityNamedTree extends DAFEntityNamed
{
    protected List<DAFEntityNamedTree> children = null;

    protected DAFEntityNamedTree parent = null;

    /**
     * @return Returns the children.
     */
    @OneToMany
    @OrderBy("name")
    @JoinColumn(name = "parent")
    @Cascade( { org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
    public List<DAFEntityNamedTree> getChildren()
    {
        return children;
    }

    /**
     * @return Returns the parent.
     */
    @ManyToOne
    @JoinColumn(name = "parent", insertable = false, updatable = false)
    public DAFEntityNamedTree getParent()
    {
        return parent;
    }
   
    /**
     * @param children The children to set.
     */
    public void setChildren(List<DAFEntityNamedTree> children)
    {
        this.children = children;
    }

    /**
     * @param parent The parent to set.
     */
    public void setParent(DAFEntityNamedTree parent)
    {
        this.parent = parent;
    }
}


I also have a superclass used to define a name property:

Code:
@EmbeddableSuperclass(access = AccessType.PROPERTY)
public abstract class DAFEntityNamed extends DAFEntity
{
    protected String name = null;

    /**
     * @return Returns the name.
     */
    @NotNull
    public String getName()
    {
        return name;
    }

    /**
     * @param name The name to set.
     */
    public void setName(String name)
    {
        this.name = name;
    }
}


and a superclass used to define an id property:

Code:
@EmbeddableSuperclass(access = AccessType.PROPERTY)
public abstract class DAFEntity
{
    protected Integer id = null;

    /**
     * @return Returns the id.
     */
    @Id(generate = GeneratorType.IDENTITY)
    public Integer getId()
    {
        return id;
    }

    /**
     * TODO Document this method
     *
     * @return boolean
     */
    @Transient
    public boolean isNew()
    {
        return (this.id ==null);
    }

    /**
     * @param id The id to set.
     */
    public void setId(Integer id)
    {
        this.id = id;
    }
}


If I setup my domain object so that it extends the base abstract class DAFEntityNamedTree as it is shown below, I get the following message when trying to run the hbm2ddl tool - org.hibernate.AnnotationException: Unable to find entity com.compudata.daf.domain.DAFEntityNamedTree.

Code:
@Entity
public class Category extends DAFEntityNamedTree
{
}


If I put the @Entity annotation on the DAFEntityNamedTree, the hbm2ddl tools completes but I end up with a DAFEntityNamedTree table in the database, with the parent column in the Category table referencing the id column of DAFEntityNamedTree via a foreign key. I want the parent column on the Category table to reference itself and for there not to be a DAFEntityNamedTree table in the database at all. What am I doing wrong that's preventing this from happening?

Here's the SQL code that gets created by hbm2ddl when I do have the @Entity annotation on the DAFEntityNamedTree abstract class:
Code:
drop table if exists Category;
drop table if exists DAFEntityNamedTree;
create table Category (id integer not null auto_increment, name varchar(255) not null, parent integer, primary key (id), unique (name, parent)) type=InnoDB;
create table DAFEntityNamedTree (id integer not null auto_increment, name varchar(255) not null, parent integer, primary key (id)) type=InnoDB;
alter table Category add index FK6DD211EDF051E2F (parent), add constraint FK6DD211EDF051E2F foreign key (parent) references DAFEntityNamedTree (id);
alter table DAFEntityNamedTree add index FK8FFD372B219C50A2 (parent), add constraint FK8FFD372B219C50A2 foreign key (parent) references Category (id);


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 23, 2006 1:16 pm 
Newbie

Joined: Sat Jan 07, 2006 5:18 pm
Posts: 19
I've tested this against Hibernate Annotations 3.1beta8 and got a slightly different error message, but the same results. Here's the new error:

Code:
org.hibernate.AnnotationException: @OneToOne or @ManyToOne on domain.Category.parent references an unknown entity: domain.DAFEntityNamedTree

This error makes sense to me, but I'm not sure how I go about solving it.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 23, 2006 7:09 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
You cannot do an association with a non entity superclass. So put your association in each subclass (ie don't use DAFEntityNamedTree as the targetEntity either implicit or explicit)

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 23, 2006 7:44 pm 
Newbie

Joined: Sat Jan 07, 2006 5:18 pm
Posts: 19
Ok, here are my changes:

Code:
@MappedSuperclass
public abstract class DAFEntityNamedTree extends DAFEntityNamed
{
    protected List<DAFEntityNamedTree> children = null;

    protected DAFEntityNamedTree parent = null;   

    /**
     * @param children The children to set.
     */
    public void setChildren(List<DAFEntityNamedTree> children)
    {
        this.children = children;
    }

    /**
     * @param parent The parent to set.
     */
    public void setParent(DAFEntityNamedTree parent)
    {
        this.parent = parent;
    }
}


Code:
@Entity
public class Category extends DAFEntityNamedTree
{
    /**
     * @return Returns the children.
     */
    @OneToMany
    @OrderBy("name")
    @JoinColumn(name = "parent")
    @Cascade( { org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
    public List<Category> getChildren()
    {
        List<Category> list = new ArrayList<Category>();
        for (DAFEntityNamedTree dent : this.children)
        {
            list.add((Category)dent);
        }
        return list;
    }

    /**
     * @return Returns the parent.
     */
    @ManyToOne
    @JoinColumn(name = "parent", insertable = false, updatable = false)
    public Category getParent()
    {
        return (Category)parent;
    }
   
    /*    (non-Javadoc)
     *    @see com.compudata.daf.domain.DAFEntityNamedTree#getChildByName(java.lang.String)
     */
    public Category getChildByName(String name)
    {
        return (Category)super.getChildByName(name);
    }
}


I'm now getting the following exception after I delete an entity and then reference the db again:

Code:
org.springframework.orm.hibernate3.HibernateSystemException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.compudata.daf.domain.Category.children; nested exception is org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.compudata.daf.domain.Category.children
org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: com.compudata.daf.domain.Category.children
   at org.hibernate.engine.Collections.processDereferencedCollection(Collections.java:96)
   at org.hibernate.engine.Collections.processUnreachableCollection(Collections.java:39)
   at org.hibernate.event.def.AbstractFlushingEventListener.flushCollections(AbstractFlushingEventListener.java:217)
   at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:77)
   at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:35)
   at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:976)
   at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:135)
   at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:113)
   at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1600)
   at org.springframework.orm.hibernate3.HibernateTemplate$27.doInHibernate(HibernateTemplate.java:798)
   at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:365)
   at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:796)
   at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:788)
   at com.compudata.daf.data.hibernate.AcsDaoHibernate.getAll(AcsDaoHibernate.java:31)
   at com.compudata.daf.business.EnvironmentManager.getAcss(EnvironmentManager.java:321)
   at com.compudata.daf.business.EnvironmentManagerTests.testDeleteAcs(EnvironmentManagerTests.java:221)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at junit.framework.TestCase.runTest(TestCase.java:154)
   at junit.framework.TestCase.runBare(TestCase.java:127)
   at junit.framework.TestResult$1.protect(TestResult.java:106)
   at junit.framework.TestResult.runProtected(TestResult.java:124)
   at junit.framework.TestResult.run(TestResult.java:109)
   at junit.framework.TestCase.run(TestCase.java:118)
   at junit.framework.TestSuite.runTest(TestSuite.java:208)
   at junit.framework.TestSuite.run(TestSuite.java:203)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)


I don't get this error if I collapse the code, i.e. move the DAFEntityNamedTree stuff into the Category class and do away with the DAFEntityNamedTree class entirely.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 23, 2006 8:12 pm 
Newbie

Joined: Sat Jan 07, 2006 5:18 pm
Posts: 19
Actually, the exception is occurring when I flush after the delete call. I'm deleting an entity that has a many-to-many relationship with the Category class (entity not shown in the Category class). The MTM relationship doesn't have any cascades, so I'm not sure why this exception is being generated.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 23, 2006 8:44 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
search the forum, this is a completly unrelated issue

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 24, 2006 12:16 am 
Newbie

Joined: Sat Jan 07, 2006 5:18 pm
Posts: 19
I'll start a new topic in that case - there doesn't appear to be anything about this topic on the forum. I searched for "no longer referenced by the owning entity instance" and also for processDereferencedCollection and didn't have any success. Thanks for your comments on this post.


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