Results 1 to 16 of 16
  1. #1
    NegroManus is offline Member
    Join Date
    Aug 2013
    Location
    Germany
    Posts
    8
    Rep Power
    0

    Default JPA design problem: Referencing entities which implement a specific interface

    Hello all,

    currently I am making my first steps regarding JPA / Hibernate. The basics are pretty clear to me, but now I encountered a design problem I could not solve.
    The problem is about the table design and/or the proper JPA/Hibernate annotations. I hope you can help me. :)

    This is the class diagram of the entities I want to persist:

    I want to keep track of the Flights of the two completely different classes: Duck (which is an Animal) and Plane, which both implement the interface Flyable.
    A Flight has a reference to a single Flyable object. A Flyable has references to a set of Flights.

    So I thought of the following tables:

    My problem is, how do I reference a Flyable entity? I cannot use a base table "flyable" for Ducks and Planes, because Duck already has a parent table: "animal".

    My classes with the JPA annotations so far look like this:
    Java Code:
    @Entity
    @Table(name = "flight")
    public class Flight
    {
    	@Id
    	@GeneratedValue
    	@Column(name = "id")
    	private long	id;
    
    	// ???
    	private Flyable	flyable;
    }
    EDIT: added the missing method (see this post: JPA design problem: Referencing entities which implement a specific interface)
    Java Code:
    public interface Flyable
    {
    	public Set<Flight> getFlights();
    }
    Java Code:
    @Entity
    @Table(name = "animal")
    @Inheritance(strategy = InheritanceType.JOINED)
    public abstract class Animal
    {
    	@Id
    	@GeneratedValue
    	@Column(name = "id")
    	private long				id;
    }
    Java Code:
    @Entity
    @Table(name = "duck")
    public class Duck extends Animal implements Flyable
    {
    
    }
    Java Code:
    @Entity
    @Table(name = "plane")
    public class Plane implements Flyable
    {
    	@Id
    	@GeneratedValue
    	@Column(name = "id")
    	private long				id;
    }
    What is the correct annotation for the "flyable" attribute of the Flight class? Or is there another solution to persist my classes?
    I would really appreciate any help you can offer me!

    Regards,
    NegroManus
    Last edited by NegroManus; 08-08-2013 at 05:21 PM. Reason: fix in table diagram

  2. #2
    gimbal2 is offline Just a guy
    Join Date
    Jun 2013
    Location
    Netherlands
    Posts
    3,082
    Rep Power
    4

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    you can't make up something and then try to make an API do what you want, you need to do create a design that conforms with the rules and design of the API you're using. So first stop: the API itself.

    In this case investigate the @MappedSuperclass, @Inheritance, @DiscriminatorColumn and @DiscriminatorValue annotations of JPA. You can't do the mapping itself with an interface but you can do it with an abstract base class and specific table design.
    "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis

  3. #3
    NegroManus is offline Member
    Join Date
    Aug 2013
    Location
    Germany
    Posts
    8
    Rep Power
    0

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    I suspected that JPA cannot do this exactly that way, but I needed to make clear what I want - from a Java developer's point of view. I have already tried to find a solution by taking a look at the JPA API, but I could not find something. :-/
    Anyway, thank you for your hints, I will take a deeper look at those annotations.


    EDIT: Ok, so I have taken a look at the annotations and am a little bit smarter now. But I still have the problem that I cannot create an abstract base class for Duck and Plane, since Duck already has an abstract base class (Animal) and multiple inheritance is not possible in Java.
    Last edited by NegroManus; 08-08-2013 at 10:50 AM.

  4. #4
    gimbal2 is offline Just a guy
    Join Date
    Jun 2013
    Location
    Netherlands
    Posts
    3,082
    Rep Power
    4

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    Quote Originally Posted by NegroManus View Post
    I suspected that JPA cannot do this exactly that way, but I needed to make clear what I want - from a Java developer's point of view. I already tried to find a solution by taking a look at the JPA API, but I could not find something. :-/
    Proof enough that you need a book to use complex APIs - I recommend 'Pro JPA 2'. Buy it, borrow it, download it, whatever but please, make your life easier. Contrary to what a wagging finger response might emotionally trigger you to assume: I -do- care that you are helped. I care a lot, or else I wouldn't risk my job spending way too much time hanging around in forums trying to help people to learn how to find their own information.
    Last edited by gimbal2; 08-08-2013 at 10:48 AM.
    "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis

  5. #5
    NegroManus is offline Member
    Join Date
    Aug 2013
    Location
    Germany
    Posts
    8
    Rep Power
    0

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    Maaan, you're giving me nothing! :-P
    Your aim to help the people to help themselves is quite noble and normally I would fight with you side by side. I just thought, "I just need to persist some pretty simple classes, so do a little bit of googling and there you go". But then I encountered my problem and could not believe that this could be so uncommon and difficult. It really gives me headaches.

    So, now I googled "JPA tutorial" and I will read this one for a start: Introduction to the Java Persistence API - The Java EE 6 Tutorial
    Maybe I'll take a look at this book later when I have some time...

  6. #6
    gimbal2 is offline Just a guy
    Join Date
    Jun 2013
    Location
    Netherlands
    Posts
    3,082
    Rep Power
    4

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    Perhaps your Animal class is that which needs the MappedSuperClass annotation.

    Well now that you're taking a look I'll give an example from an application I maintain. Its a financial application but it has a similar structure as you are attempting to model. There is a BasePolicyDeductible...

    Java Code:
    @MappedSuperclass
    public abstract class BasePolicydeductible { // Animal
    
        @Id
        @GeneratedValue(strategy = IDENTITY)
        @Column(name = "idpolicydeductible", nullable = false)
        private Integer idpolicydeductible;
    
        ...
    }
    and a PolicyDeductible on top of that:

    Java Code:
    @Entity
    @Table(name = "policydeductible")
    @Inheritance
    @DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
    public abstract class Policydeductible extends BasePolicydeductible { // Duck/Plane
       ...
    }
    and there are two specific deductible types mapped in the same table:

    Java Code:
    @Entity
    @DiscriminatorValue("A")
    public class PolicydeductibleAmount extends Policydeductible  { // Duck entity
       ...
    }
    
    @Entity
    @DiscriminatorValue("T")
    public class PolicydeductibleText extends Policydeductible { // Plane entity
       ...
    }
    See how that works? In stead of having two tables and one entity, you have one table that translates to two entities. And then you have something that JPA can work with.

    Of course in your original design, Duck and Plane end up in different tables. I would second guess that design based on your "it needs to be flyable" requirement, but perhaps using the @SecondaryTable might get you closer to what you want; I must admit I never used that myself and it seems like a door into wonky design to me, but I'm not perfect myself so I can easily be wrong. Here is an example:

    http://uaihebert.com/?p=46
    Last edited by gimbal2; 08-08-2013 at 11:31 AM.
    "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis

  7. #7
    NegroManus is offline Member
    Join Date
    Aug 2013
    Location
    Germany
    Posts
    8
    Rep Power
    0

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    Quote Originally Posted by gimbal2
    Perhaps your Animal class is that which needs the MappedSuperClass annotation.
    That would mean, Plane would have to extend Animal as well. This way a Plane becomes an Animal. :D

    EDIT: This post was sent before you edited the example in
    Last edited by NegroManus; 08-08-2013 at 12:50 PM.

  8. #8
    gimbal2 is offline Just a guy
    Join Date
    Jun 2013
    Location
    Netherlands
    Posts
    3,082
    Rep Power
    4

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    whoops, didn't see your new addition. Yep, so perhaps that Animal thing is not a class but an interface and you need Flyable to be your mappedsuperclass?
    "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis

  9. #9
    NegroManus is offline Member
    Join Date
    Aug 2013
    Location
    Germany
    Posts
    8
    Rep Power
    0

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    Packing Duck and Plane in one table would be really bad because they have nothing in common.

    Animal cannot be just an interface because it is used as a base class for many other child and grandchild classes apart from Duck (I omitted them for simplicity).

    The solution that would give me the least headaches, is defining a common parent class AbstractFlyable above Animal and Plane. Of course the most animals cannot fly but there are no needless attributes attached to Flyable.
    Sure, it would be bad object-oriented design, but all other solutions would be even worse or not possible with JPA.

    Another idea I had was to create a table named "flyable" which just contains the IDs of all entities that can fly (all IDs of Duck entities and all IDs of Plane entities). But I assume that cannot be mapped with JPA as well:
    Last edited by NegroManus; 08-08-2013 at 01:09 PM.

  10. #10
    gimbal2 is offline Just a guy
    Join Date
    Jun 2013
    Location
    Netherlands
    Posts
    3,082
    Rep Power
    4

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    Quote Originally Posted by NegroManus View Post
    Packing Duck and Plane in one table would be really bad because they have nothing in common.
    You could also turn it around: a duck and a plane both have a flight. Then you don't need any inheritance at all, and the Flyable interface becomes this:

    Java Code:
    public interface Flyable {
      public Flight getFlight();
    }
    I don't know but that rings the most true to me and doesn't resort to complexity and wonky database design.

    BUT I don't really know the specifics of what you're trying to model, so I keep on guessing. Also as a side note: I'm really trying to find a JPA way to get you to a point where you have something you want. Hibernate has a specific feature that allows you to do what you want, but its usage is... how to put it... your code will suck.
    Last edited by gimbal2; 08-08-2013 at 01:14 PM.
    "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis

  11. #11
    NegroManus is offline Member
    Join Date
    Aug 2013
    Location
    Germany
    Posts
    8
    Rep Power
    0

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    Oh, sorry *facepalm*.
    Actually the Flyable interface has the method getFlights(), I just forgot it in the first post.

    Java Code:
    public interface Flyable
    {
    	public Set<Flight> getFlights();
    }
    As you can see in the class diagram in the first post, there is a OneToMany relationship from Flyable to Flight and a ManyToOne relationship from Flight to Flyable, respectively.
    The attribute "flyable" in the class Flight is just for enabling bidirectional navigation.

    I will edit my first post accordingly.
    Last edited by NegroManus; 08-08-2013 at 01:48 PM.

  12. #12
    gimbal2 is offline Just a guy
    Join Date
    Jun 2013
    Location
    Netherlands
    Posts
    3,082
    Rep Power
    4

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    Yes but that doesn't change anything about the design, you will still have a Flight with one property that maps to X different tables.

    *sigh* well I guess I'll have to spill the beans: JPA does not provide any direct solution for this that I know of but Hibernate does through the @Any annotation, which basically says "this field maps to any other entity" although you still have to tell Hibernate which one it is. Example:

    Java Code:
        @Any(metaColumn = @Column(name = "Entity"))
        @AnyMetaDef(idType = "integer", metaType = "integer", metaValues = {
            @MetaValue(value = "1", targetEntity = Duck.class),
            @MetaValue(value = "2", targetEntity = Plane.class)
        })
        @JoinColumn(name = "ParentID")
        private Object parentEntityObject;
    This requires two columns in the table so Hibernate can know what you're talking about

    - Entity: this field identifies what the type of the object is (so in the above example an integer value of 1 means its a Duck and an integer value of 2 means its a Plane)
    - parentID: this is the ID of the physical record that Hibernate will map into it

    Referential integrity goes right out the window this way, and you'll need to do type casting to be able to use the mapped property. If you make all your mapped objects implement your Flyable interface then you can typecast to that.
    "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis

  13. #13
    NegroManus is offline Member
    Join Date
    Aug 2013
    Location
    Germany
    Posts
    8
    Rep Power
    0

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    Quote Originally Posted by gimbal2 View Post
    Yes but that doesn't change anything about the design, you will still have a Flight with one property that maps to X different tables.
    Yeah, I know that it does not change the design, it just means that your solution above with defining a "flight" attribute in each Flyable class table would not work because it is an OneToMany relationship.

    Quote Originally Posted by gimbal2 View Post
    *sigh* well I guess I'll have to spill the beans: JPA does not provide any direct solution for this that I know of but Hibernate does through the @Any annotation, which basically says "this field maps to any other entity" although you still have to tell Hibernate which one it is.
    I think this is as best as it gets. I rather have a good domain class model and a somehow inconvenient/unusual persistence layer than the other way around.
    Thank you for finding that possibility!
    I also found a website that explains the problem & solution quite nicely: Eyal Lupu Java Blog >> Hibernate - the @Any annotation
    According to this article, the "parentEntityObject" in your example code does not have to be of Type Object, but can as well be an interface which is implemented by all target entities (-> Flyable).

    I'm always open to JPA-conform redesigns of my domain class model or my tables. I just found no possibility.
    Maybe you or me or someone else comes up with a better idea in the future.
    Last edited by NegroManus; 08-08-2013 at 02:24 PM.

  14. #14
    gimbal2 is offline Just a guy
    Join Date
    Jun 2013
    Location
    Netherlands
    Posts
    3,082
    Rep Power
    4

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    If you'd want to do it using plain JPA you need two nullable columns in your Flight table and two properties in your Flight entity; one for Plane and one for Duck.

    We're also blessed with the Any annotation in our domain model and the person who made the decision to use it told me that now after the fact when its already too late, he'd rather have used the multiple ID design. Just so you know.
    "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis

  15. #15
    NegroManus is offline Member
    Join Date
    Aug 2013
    Location
    Germany
    Posts
    8
    Rep Power
    0

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    Quote Originally Posted by gimbal2 View Post
    If you'd want to do it using plain JPA you need two nullable columns in your Flight table and two properties in your Flight entity; one for Plane and one for Duck.
    I cannot quite follow you, sorry, can you explain what you mean? Or maybe draw a little entity relationship model.
    (Of course I would like to use plain JPA, I just did not find a possibility)

    Quote Originally Posted by gimbal2 View Post
    We're also blessed with the Any annotation in our domain model and the person who made the decision to use it told me that now after the fact when its already too late, he'd rather have used the multiple ID design. Just so you know.
    Same here. What do you mean with "multiple ID design"?

  16. #16
    gimbal2 is offline Just a guy
    Join Date
    Jun 2013
    Location
    Netherlands
    Posts
    3,082
    Rep Power
    4

    Default Re: JPA design problem: Referencing entities which implement a specific interface

    Java Code:
    public class Flight {
      @ManyToOne
      @JoinColumn(name="duck_id")
      private Duck duck;
    
      @ManyToOne
      @JoinColumn(name="plane_id")
      private Plane plane;
    
      ...
    }
    Fill one or the other. Equally ugly, but at least no "any" AND you have referential integrity, plus support for cascading...
    "Syntactic sugar causes cancer of the semicolon." -- Alan Perlis

Similar Threads

  1. problem in comparator interface implementing
    By fractal in forum New To Java
    Replies: 11
    Last Post: 06-11-2012, 10:33 PM
  2. NEED HELP in IMPLEMENTING A GIVEN INTERFACE!
    By wasiqjaved in forum New To Java
    Replies: 0
    Last Post: 10-03-2011, 12:40 PM
  3. Implementing Interface
    By mew in forum New To Java
    Replies: 4
    Last Post: 02-16-2010, 03:33 PM
  4. help! implementing an interface
    By manda147 in forum New To Java
    Replies: 28
    Last Post: 11-17-2008, 04:27 AM
  5. Implementing an interface
    By bugger in forum Advanced Java
    Replies: 1
    Last Post: 01-09-2008, 01:35 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •