JPA polymorphic oneToMany

I could not figure out how to clear the tag cloud using JPA, where each db object can have many tags.

eg

A message can have 0 or more tags. A user can have 0 or more tags.

Is there a better way in JPA than making all object subsites something like an abstract Taggable class? If the tag object refers to many taggables.

Edit: The tag cloud is just a sample to simplify the problem I'm experiencing. In my scenario, the relationship should be OneToMany where the tag cannot be reused.

Thank you

+5
java polymorphism jpa
source share
4 answers

This is similar to ManyToMany, not Many. Users can have multiple tags, and a tag can be associated with multiple users?

You need only such a superclass if you want to relate to a tag in one collection containing each object tagged with this tag. Do you have a requirement for the tag.getOneGiantCollectionOfEveryTaggedEntity() method?

Since the marked objects do not seem to have anything in common, does such a collection really have any meaning in your application domain? Perhaps it can also be quite large, and not the fact that you really want to work with object relationships. From a practical point of view, not knowing about your use case, it seems that tag.getTaggedUsers() , tag.getTaggedPosts() , etc. More useful.

Sorry, I think I am asking more questions than giving answers, but it is not clear that you want your final domain to look like this :)

edit:

Perhaps the actual answer then to the question asked is simply "No, Hibernate will not display to you an unprocessed collection of types that do not have a common ancestor that simply has foreign keys to your entity with everyone." You do not have to impose a “fake” superclass on your entities, but if you do not, you will have to create a join table.

.

+1
source share

Is there a better way in JPA than making all subclasses of objects something like an abstract Taggable class?

Let's forget an example: JPA supports polymorphic associations, but target classes must be part of the inheritance hierarchy. And here are a few rules of thumb on inheritance strategies:

  • SINGLE_TABLE:
    • All classes in the hierarchy are displayed in one table.
    • This strategy provides good support for polymorphic relationships between entities and queries that span an entire class hierarchy.
    • May contain empty fields for some subclass data
  • TABLE_PER_CLASS:
    • Each class in the hierarchy is mapped to a separate table and therefore provides poor support for polymorphic relationships
    • requires a SQL connection or separate SQL queries for each subclass
  • Joined
    • no null fields => compact data
    • This provides good support for polymorphic relationships, but requires one or more merging operations - can lead to reduced performance.

In short, if your subclasses declare relatively few properties, prefer the SINGLE_TABLE strategy. If not, use the JOINED strategy if you do not have a deep hierarchy (in this case, the cost of unions can become more expensive than unions, and then TABLE_PER_CLASS will be "worse").

References

  • JPA 1.0 Specification
    • Section 2.1.9 Inheritance
    • Section 2.1.10 "2.1.10 Inheritance Matching Strategies"
+1
source share

why don't you just draw a collection of tags or even strings?

sudocode:

 @Entity @Table(name="entities") class MyEntity{ long id; String someField; @ManyToMany(targetEntity=Tag.class) @JoinTable(name="entities_to_tags", joinColumns={ @JoinColumn(name="id", referencedColumnName="entity_id", inverseJoinColumns={ @JoinColumn(name="id", referencedColumnName="tag_id")}) List<Tag> tags; [...getter&setter...] } @Entity @Table(name="tags") class Tag{ @Id @GeneratedValue long id; String title; [....getter & setter...] } 
0
source share

If you do not need polymorphic queries, such as "get all tagged with Foo", you can also enter a new object (say TaggingTarget ) and create a one-to-one one-to-one relationship from User ( Post , etc.) to TaggingTarget and the relationship many to many between TaggingTarget and Tag :

 @Entity public class User { @OneToOne private TaggingTarget target; ... } @Entity public class TaggingTarget { @ManyToMany(...) private Set<Tag> tags; ... } @Entity public class Tag { @ManyToMany(...) private Set<TagTarget> targets; ... } 

The difference from Affe's solution is that you don't need tag.getTaggedUsers() , tag.getTaggedPosts() , etc. and can add new tagged objects without changing the Tag . Tagged objects can be queried using JPQL:

 select u from User u where :tag member of u.target.tags 

or

 select u from User u join u.target.tags t where t.name = :name 
0
source share

All Articles