-->
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.  [ 3 posts ] 
Author Message
 Post subject: @Any bidirectional relationship fails
PostPosted: Thu Apr 16, 2009 6:40 pm 
Newbie

Joined: Fri Jan 23, 2009 4:02 pm
Posts: 6
Hello,

I am trying to support a legacy database that has a "note" table that links to multiple other tables using a foreign key column plus a table identifier column. I'm trying to use the @Any annotation to establish this relationship. Furthermore, I want the relationship to be bidirectional and owned by the parent, so for a parent like "person" I can add a note and flush the parent without worrying about persisting the new note.

However, the following mapping is resulting in an exception during session factory configuration:
Code:
org.hibernate.MappingException: Duplicate property mapping of _notesBackref found in com.builderadius.blueserve.model.Note

which reminds me of a resolved Hibernate bug (2598).

Any ideas how to fix this mapping?

Thank you,
Noah

Hibernate version:
hibernate-core 3.3.1.GA
hibernate-annotations 3.4.0.GA
jboss-embedded beta3.SP4

Mapping documents:

Person class (a parent)
Code:
@Entity @Table(name = "person")
public class Person
{
    private Set<Note> notes;
    ...
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @Cascade( { org.hibernate.annotations.CascadeType.SAVE_UPDATE,
            org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
    @JoinColumn(name = "RelatedRecNum", nullable = false)
    public Set<Note> getNotes()
    {
        return this.notes;
    }

    public void setNotes(final Set<Note> notes)
    {
        this.notes = notes;
    }
}


Note class (the child)
Code:
@Entity @Table(name = "note")
public class Note
{
    ...
    @Any(metaColumn = @Column(name = "RelatedRecType"), optional = false)
    @AnyMetaDef(idType = "integer", metaType = "string", metaValues = {
            @MetaValue(targetEntity = Person.class, value = "person"),
            @MetaValue(targetEntity = Group.class, value = "group") })
    @JoinColumn(name = "RelatedRecNum", insertable = false, updatable = false, nullable = false)
    @NotNull
    public BlueserveEntity getParent()
    {
        return this.parent;
    }

    public void setParent(final BlueserveEntity parent)
    {
        this.parent = parent;
    }
}


Full stack trace of any exception that occurs:
[testng] ERROR [org.jboss.kernel.plugins.dependency.AbstractKernelController] Error installing to Start: name=persistence.units:jar=test-build.jar,unitName=blueserve state=Create
[testng] javax.persistence.PersistenceException: [PersistenceUnit: blueserve] Unable to build EntityManagerFactory
[testng] at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:677)
[testng] at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:132)
[testng] at org.jboss.ejb3.entity.PersistenceUnitDeployment.start(PersistenceUnitDeployment.java:259)
[testng] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[testng] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
[testng] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
[testng] at java.lang.reflect.Method.invoke(Method.java:585)
[testng] at org.jboss.reflect.plugins.introspection.ReflectionUtils.invoke(ReflectionUtils.java:56)
[testng] at org.jboss.reflect.plugins.introspection.ReflectMethodInfoImpl.invoke(ReflectMethodInfoImpl.java:110)
[testng] at org.jboss.joinpoint.plugins.BasicMethodJoinPoint.dispatch(BasicMethodJoinPoint.java:66)
[testng] at org.jboss.kernel.plugins.dependency.KernelControllerContextAction$JoinpointDispatchWrapper.execute(KernelControllerContextAction.java:214)
[testng] at org.jboss.kernel.plugins.dependency.ExecutionWrapper.execute(ExecutionWrapper.java:45)
[testng] at org.jboss.kernel.plugins.dependency.KernelControllerContextAction.dispatchExecutionWrapper(KernelControllerContextAction.java:108)
[testng] at org.jboss.kernel.plugins.dependency.KernelControllerContextAction.dispatchJoinPoint(KernelControllerContextAction.java:69)
[testng] at org.jboss.kernel.plugins.dependency.LifecycleAction.installActionInternal(LifecycleAction.java:221)
[testng] at org.jboss.kernel.plugins.dependency.KernelControllerContextAction.installAction(KernelControllerContextAction.java:135)
[testng] at org.jboss.kernel.plugins.dependency.KernelControllerContextAction.installAction(KernelControllerContextAction.java:46)
[testng] at org.jboss.dependency.plugins.action.SimpleControllerContextAction.simpleInstallAction(SimpleControllerContextAction.java:62)
[testng] at org.jboss.dependency.plugins.action.AccessControllerContextAction.install(AccessControllerContextAction.java:71)
[testng] at org.jboss.dependency.plugins.AbstractControllerContextActions.install(AbstractControllerContextActions.java:51)
[testng] at org.jboss.dependency.plugins.AbstractControllerContext.install(AbstractControllerContext.java:327)
[testng] at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:1309)
[testng] at org.jboss.dependency.plugins.AbstractController.incrementState(AbstractController.java:734)
[testng] at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:862)
[testng] at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:784)
[testng] at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:574)
[testng] at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:398)
[testng] at org.jboss.kernel.plugins.dependency.AbstractKernelController.install(AbstractKernelController.java:96)
[testng] at org.jboss.kernel.plugins.dependency.AbstractKernelController.install(AbstractKernelController.java:90)
[testng] at org.jboss.ejb3.MCKernelAbstraction.install(MCKernelAbstraction.java:151)
[testng] at org.jboss.ejb3.Ejb3Deployment.startPersistenceUnits(Ejb3Deployment.java:604)
[testng] at org.jboss.ejb3.Ejb3Deployment.start(Ejb3Deployment.java:400)
[testng] at org.jboss.ejb3.deployers.EJBStage2Deployer.deploy(EJBStage2Deployer.java:53)
[testng] at org.jboss.ejb3.deployers.EJBStage2Deployer.deploy(EJBStage2Deployer.java:37)
[testng] at org.jboss.deployers.spi.deployer.helpers.AbstractSimpleRealDeployer.internalDeploy(AbstractSimpleRealDeployer.java:65)
[testng] at org.jboss.deployers.spi.deployer.helpers.AbstractRealDeployer.deploy(AbstractRealDeployer.java:50)
[testng] at org.jboss.deployers.plugins.deployers.DeployerWrapper.deploy(DeployerWrapper.java:169)
[testng] at org.jboss.deployers.plugins.deployers.DeployersImpl.doInstallParentFirst(DeployersImpl.java:853)
[testng] at org.jboss.deployers.plugins.deployers.DeployersImpl.install(DeployersImpl.java:794)
[testng] at org.jboss.dependency.plugins.AbstractControllerContext.install(AbstractControllerContext.java:327)
[testng] at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:1309)
[testng] at org.jboss.dependency.plugins.AbstractController.incrementState(AbstractController.java:734)
[testng] at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:862)
[testng] at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:784)
[testng] at org.jboss.dependency.plugins.AbstractController.change(AbstractController.java:622)
[testng] at org.jboss.dependency.plugins.AbstractController.change(AbstractController.java:411)
[testng] at org.jboss.deployers.plugins.deployers.DeployersImpl.process(DeployersImpl.java:498)
[testng] at org.jboss.deployers.plugins.main.MainDeployerImpl.process(MainDeployerImpl.java:506)
[testng] at org.jboss.embedded.DeploymentGroup.process(DeploymentGroup.java:127)
[testng] at org.jboss.embedded.Bootstrap.deployResourceBases(Bootstrap.java:289)
[testng] at org.jboss.seam.mock.EmbeddedBootstrap.startAndDeployResources(EmbeddedBootstrap.java:15)
[testng] at org.jboss.seam.mock.AbstractSeamTest.startJbossEmbeddedIfNecessary(AbstractSeamTest.java:1024)
[testng] at org.jboss.seam.mock.AbstractSeamTest.startSeam(AbstractSeamTest.java:915)
[testng] at org.jboss.seam.mock.SeamTest.startSeam(SeamTest.java:58)
[testng] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[testng] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
[testng] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
[testng] at java.lang.reflect.Method.invoke(Method.java:585)
[testng] at org.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:580)
[testng] at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:398)
[testng] at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:145)
[testng] at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:82)
[testng] at org.testng.SuiteRunner.privateRun(SuiteRunner.java:278)
[testng] at org.testng.SuiteRunner.run(SuiteRunner.java:198)
[testng] at org.testng.TestNG.createAndRunSuiteRunners(TestNG.java:821)
[testng] at org.testng.TestNG.runSuitesLocally(TestNG.java:788)
[testng] at org.testng.TestNG.run(TestNG.java:708)
[testng] at org.testng.TestNG.privateMain(TestNG.java:858)
[testng] at org.testng.TestNG.main(TestNG.java:831)
[testng] Caused by: org.hibernate.MappingException: Duplicate property mapping of _notesBackref found in com.builderadius.model.Note
[testng] at org.hibernate.mapping.PersistentClass.checkPropertyDuplication(PersistentClass.java:459)
[testng] at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:449)
[testng] at org.hibernate.mapping.RootClass.validate(RootClass.java:192)
[testng] at org.hibernate.cfg.Configuration.validate(Configuration.java:1108)
[testng] at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1293)
[testng] at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:859)
[testng] at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:669)
[testng] ... 68 more

Name and version of the database you are using:

MySQL 5.0.45


Top
 Profile  
 
 Post subject: Re: @Any bidirectional relationship fails
PostPosted: Wed Jun 24, 2009 9:34 pm 
Beginner
Beginner

Joined: Fri Mar 26, 2004 8:19 am
Posts: 49
What if you mapped both relationships (thinking only from the Parent perspective)?

It costs you nothing to have both mapped with lazy loading being the default behavior in 3.0+. Set the getters for both type of Note to private and create a new accessor method that returns one or the other depending on the 'choice' field.

My hunch though is that there might be a better way to model this by introducing a new base type of Note from which the existing notes derive from.


Top
 Profile  
 
 Post subject: Re: @Any bidirectional relationship fails
PostPosted: Fri Jul 10, 2009 8:41 am 
Newbie

Joined: Fri Jan 23, 2009 4:02 pm
Posts: 6
Thanks for the suggestion, Dan. I gave up on the @Any annotation and used inheritance instead. This solution requires more classes, but each class is easier to work with because the Note parent is properly type constrained. Here's roughly the working code I ended up with:

Person class (a parent)

Code:
@Entity @Table(name = "person")
public class Person
{
    private Set<PersonNote> notes;
    ...
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @Cascade( { org.hibernate.annotations.CascadeType.SAVE_UPDATE,
            org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
    @JoinColumn(name = "RelatedRecNum", nullable = false)
    public Set<PersonNote> getNotes()
    {
        return this.notes;
    }

    public void setNotes(final Set<PersonNote> notes)
    {
        this.notes = notes;
    }
}


Note class (the child)

Code:
@Entity @Table(name = "note")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "RelatedRecType")
@ForceDiscriminator
public abstract class Note
{
    ...

    @Transient
    abstract public BlueserveEntity getParent();
}


Note class (a concrete child)

Code:
@Entity
@DiscriminatorValue("Person")
public class PersonNote extends Note
{
    ...
    @ManyToOne(optional = false)
    @JoinColumn(name = "RelatedRecNum", insertable = false, nullable = false, updatable = false)
    @NotNull
    @Override
    public Person getParent()
    {
        return parent;
    }

    public void setParent(final Person parent)
    {
        this.parent = parent;
    }
}


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