Hi all,
I am working on a project in which inheritance is done through interfaces only - two different implementation classes that implement the same interface don't have a common parent class.
A human can be a person or an hero. This is modeled by a relationship between their respective interfaces. Thus, IPerson and IHero extend IHuman.
For both person and hero we have implementation classes (PersonImpl and HeroImpl) that implement the interfaces IPerson and IHero. We consider human as "fully abstract" and therefore
we have no concrete class representing it.
The PersonImpl and HeroImpl have an object (IPersonID and IHeroID respectively) as @EmbeddedId. The IDs hierarchy is done in a similar way.
Here are some code snippets:
Code:
/************interfaces****************/
public interface IHuman{
/*...*/
}
public interface IPerson extends IHuman{
/*some methods here*/
}
public interface IHero extends IHuman{
/*...*/
}
/************entities****************/
@Entity
@Table( name = "person", schema = "mySchema" )
public class PersonImpl implements IPerson{
private IPersonID myID;
@EmbeddedId
@AttributeOverrides( { @AttributeOverride( name = "value", column = @Column( name = "id_value" ) ),
@AttributeOverride( name = "classType", column = @Column( name = "id_type" ) ) } )
@Target( IPersonID.class )
public final IPersonID getID() {
return myID;
}
/*...*/
}
@Entity
@Table( name = "person", schema = "mySchema" )
public class HeroImpl implements IHero{
private IHeroID myID;
@EmbeddedId
@AttributeOverrides( { @AttributeOverride( name = "value", column = @Column( name = "id_value" ) ),
@AttributeOverride( name = "classType", column = @Column( name = "id_type" ) ) } )
@Target( IHeroId.class )
public final IHeroId getID() {
return myID;
}
/*...*/
}
/************ids interfaces****************/
public interface ICustomId{
/*...*/
}
public interface IPersonId extends ICustomId{
/*...*/
}
public interface IHeroId extends ICustomId{
/*...*/
}
/************ids implementation****************/
@MappedSuperclass
public abstract class CustomIdImpl implements ICustomId{
/*generic id implementation class, extended by all "concrete" id implementation classes*/
}
@Embeddable
public final class PersonIdImpl extends CustomIdImpl implements IPersonId {
}
@Embeddable
public final class HeroIdImpl extends CustomIdImpl implements IHeroId {
}
Now, I have another class which holds an IHuman:
Code:
@Entity
@Table( name = "Test", schema = mySchema" )
@Access( AccessType.PROPERTY )
public final class Test{
private IHuman myHuman;
@Any( metaColumn = @Column( name = "myHuman_type" ), fetch = FetchType.EAGER )
@AnyMetaDef([b] idType = "CustomIdImpl "[/b], metaType = "string", metaValues = {
@MetaValue( value = "person", targetEntity = PersonImpl .class ),
@MetaValue( value = "hero", targetEntity = HeroImpl.class ),
} )
@JoinColumn( name = "myHumanId", referencedColumnName = "human_id" )
@Cascade( { CascadeType.ALL } )
@Override
public final IHumanShared getMyHuman() {
return myDomainStructAbstractValueNullable;
}
public final void setMyHuman( IHumanShared human ) {
myHuman = human;
}
}
Is this the correct way to map it? From my understanding of the hibernate documentation "normal" polyphormism does not work when entities do not have a common ancestor class and @Any mapping has to be used instead.
All in all it seems to work but given that the idType defined in the @AnyMetaDef is an object it gets blobbed in a column and therefore embedded id values can not be queried in sql. Any ways around it?
Thanks and regards,
piro84