-->
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.  [ 2 posts ] 
Author Message
 Post subject: Mixing Inheritance Strategies with Annotations - Strange FKs
PostPosted: Thu Sep 03, 2009 4:34 pm 
Senior
Senior

Joined: Mon Jul 07, 2008 4:35 pm
Posts: 141
Location: Berlin
Hi *,

after a couple of days searching for a solution to my problem I'm finally going to bother you with that issue.

The project uses a mapping files as well as annotations. The annotations pertain a single class hierarchy.

The root looks like this

Code:
@Entity(name = "rootentity")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class RootEntity implements SomeInterface {
  ...
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id")
  private Long serialId = null;

  @OneToMany(cascade = { CascadeType.ALL }, targetEntity = EntityProp.class)
  @JoinColumn(name = "rootentity_id", referencedColumnName="id")
  @MapKey(name = "name")
  @LazyCollection(LazyCollectionOption.EXTRA)
  private Map<String, EntityProp<?>> properties = new Hashtable<String, EntityProp<?>>();

  @OneToMany(cascade = { CascadeType.ALL }, targetEntity = Representer.class)
  @JoinColumn(name = "rootentity_id", referencedColumnName="id")
  @LazyCollection(LazyCollectionOption.EXTRA)
  private Set<Representer> representations = new HashSet<Representer>();

  @ManyToOne(targetEntity = Container.class)
  @JoinColumn(name = "container_id", referencedColumnName="id")
  @ForeignKey(name="FK_RootEntity_Container")
  protected Container container;

  ...
}


The implemented interface is not relevant for persistence issues. Just giving the details in case it could be relevant.

The RootEntity is extended by five abstract children all having own fields but are annotated the same way

Code:
@Entity(name = "entitya")
@SecondaryTable(name = "entitya")
@ForeignKey(name = "FK_EntityA_RootEntity")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorFormula(<SQL making own type field the discriminator>)
public abstract class EntityA extends RootEntity {
  // own fields
}


The concrete extension classes for these children map like follows:

Code:
@Entity
@Table(name = "entitya")
public class SubEntityA extends EntityA {
  // no own fields -> no additional table columns
}


Though, I don't think the Container plays a role in the issue I'll post it, too. It is covered by a mapping file, here's a possibly relevant excerpt:

Code:
<class name="Container" table="container">

  <!-- own field mappings -->

  <!-- Collection of EntityAs -->
  <set name="entityas" inverse="true"
    cascade="save-update, delete, delete-orphan" lazy="extra">
    <key column="container_id" unique="false"
      foreign-key="FK_Container_EntityA" not-null="false" />
    <one-to-many class="EntityA" not-found="ignore" />
  </set>

  <!-- Collection of other entities extending RootEntity -->

</class>


So, the problem itself:
Anytime I create the schema for the (MySQL 5.0, InnoDB) database I end up with three foreign keys for each joined sub-class.
One, referencing the Container, one referencing the RootEntity (both perfectly alright, as I suppose), and finally one referencing the own PK having the usual Hibernate-crypted name.
Using Hibernate Annotations 3.4.0.GA will not create the schema due to a foreign key circularity dependency. My Hibernate Tools installation with Annotations 3.3.0GA does not care about this dependency and creates the schema. So, I downgraded the Hibernate Annotations Jar in the application to 3.3.0.GA and the schema creation works well. When running the application persisting an entity fails with the first attempt due to a constraint violation. Responsible is the third FK named above.
It seems to be independent of the concrete sub-classes of, e.g. EntityA. Even without them the FK is generated.

Now, my questions:
1. Where does this mentioned third FK come from? I can't figure out.
2. Why is it generated anyway?
3. Is there a way to prevent this FK from being generated?
4. Since I tried a lot of stuff, does anyone know if the general idea of the mixed inheritance strategies is actually possible with Annotations?
5. Does the second @Inheritance annotation override the previous for the concrete sub-classes?


Any help very appreciated!
Thanks already!

CU
Froestel

_________________
Have you tried turning it off and on again? [Roy]


Top
 Profile  
 
 Post subject: Re: Mixing Inheritance Strategies with Annotations - Strange FKs
PostPosted: Wed Sep 16, 2009 11:39 am 
Senior
Senior

Joined: Mon Jul 07, 2008 4:35 pm
Posts: 141
Location: Berlin
Hi again,

I found a solution to my problem that is actually straight forward.

The RootEntity class is annotated to use Single Table Inheritance.
Code:
@Entity(name = "rootentity")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorFormula(<SQL making own type field the discriminator>)
public abstract class RootEntity implements SomeInterface {
  ...
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id")
  private Long serialId = null;
  ...
}


So, the RootEntity table ends up with the properties shared among all child classes including the discriminator column.

The direct child classes each use a Join Table.
Code:
@Entity(name = "entitya")
@SecondaryTable(name = "entitya", pkJoinColumns = { @PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id") })
@ForeignKey(name = "FK_EntityA_RootEntity")
public abstract class EntityA extends RootEntity {
  // own fields
}


The table, thus, contains all properties specified by the very child class.

Each child's sub-classes are simply annotated with @Entity.
Code:
@Entity
public class SubEntityA extends EntityA {
  // no own fields -> no additional table columns
}


The java objects get persisted in the join table of their parent as well as that of the RootEntity according to where the fields where inherited from. No additional tables are generated.

Hope, it spares someone else's time on a similar case.

Thanks for your views anyway.

CU
Froestel

_________________
Have you tried turning it off and on again? [Roy]


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