I have three entities video_guide text_guide and discussion that represent type of learning material available on the platform. A student can create topic-wise boards and add learning material to them. And later view material saved to boards. I am finding it a bit of challenge to aggregate data from three different entities into Board entity, keeping the performance and code quality in check. I have come up with three approaches to implement this use case and would like to have your input on the same. We are using PostgreSQL12 with Hibernate.
Approach 1: JPA Inheritance Joined strategy. This should work but it has following downside
- Known performance issues with Inheritance mappings.
- Queries become more complex hence overall complexity of the code.
- Inheritance is not a SQL native concept but a JPA feature.
Therefore, do not see this as a good option to explore futher.
Approach 2: Individual entity mapping
@Entity
public class Board{
@Id
private long id;
@ManyToMany
private Set<VideoGuide> = new HashSet<>();
@ManyToMany
private Set<TextGuide> = new HashSet<>();
@ManyToMany
private Set<Discussion> = new HashSet<>();
------------
------------
}
This will have
- Simpler code and queries.
- Better performance on reads(DTO projections).
has following downsides
- If new type of materials are introduced in the future more associations need to be added.
- This same use case is required for other features e.g Topic page that displays all the material related to that topic. That means more duplication, more places for code change.
Approach 3: Preview table
Create a new entity material_preview which will hold previews for all material available on the platform.
@Entity
public class MaterialPreview{
@Id
private long materialId;
private String title;
---------------
---------------
}
Map MaterialPreview to Board entity
@Entity
public class Board{
@Id
private long id;
@ManyToMany
private Set<MaterialPreview> = new HashSet<>();
------------
------------
}
Every time a new material is added to the platform its preview is added to MaterialPreview. And this MaterialPreview entity will be used for mapping a material instance to other entities rather than video_guide text_guide and discussion entities.
This will
- Allow single mapping for all the material types. So, in future if new material types are added no changes to mapping will be required.
- No apparent issues with the reads performance.
has following downside
- Additional insert into
MaterialPreview. - Data redundancy. But I think this should be acceptable since the number of attributes in
MaterialPreviewwill be somewhere between 8 and 10. - Attributes not common to all material types will be null.
- Keeping
MaterialPreviewin sync with actual material tables. So, if somebody updates title of a video guide we need to update the same in preview table as well.
What do you think would work out best or some other approach I should consider? Suggestions are much appreciated.
Thanks !!