Inheritance vs composition in JPA - jpa

A legacy application persistence is based on JPA. There is an entity, People, mapped to the database table People.
Now a subset of all the rows in People needs some additional fields.
One possible solution is to use jpa inheritance and create a new entity, suppose EmployeedPeople, which extends People.
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public class People {
...
#Entity(name = “EmployeedPeople”)
public class EmployeedPeople extends People {
Alternatively I can use unidirectional one to one relationship
#Entity(name = “EmployeedPeople”)
public class EmployeedPeople {
...
#OneToOne(optional = false)
private People commonPersonData;
I thought about a third way too: the new entity is based on a database view which joins People table with EmployeedData table.
This last approach is good for reading EmployeedPeople but impractical for inserting and updating because I have to work with different entities (People and EmployeedData).
Which criteria can help in choosing the strategy ?
Which are the pros and cons of each solutions ?
In internet I have already found the following guide which compares the inheritance strategies and this one on composition but my ideas are not clear yet.

Related

Spring Data REST - How to update entities in child collections of aggregates

Following the principles of DDD and using Spring Data REST/HATEOAS what is the best way to manipulate entities in child collections.
For example:
#Entity
public class Topic{
#Id #GeneratedValue
private Long id;
private String title;
#OneToMany
private Set<Post> posts;
…
}
#Entity
public class Post{
#Id #GeneratedValue
private Long id;
private String title;
private String body;
#OneToMany
private Set<Comment> comment;
…
}
#Entity
public class Comment{
#Id #GeneratedValue
private Long id;
private String text;
}
Spring Data REST (SDR) inlines domain objects that don't have their own repositories when serializing to JSON.
{
"title" : "Spring",
"posts" : [{
"title": "Spring Boot 1.5.8",
"body": "blah",
"comments":[ {"text":"great!"} , {"text":"boo"},
{"text":"comment that should be removed by moderators"}]
}]
"_links" : {
"self" : {
"href" : "http://localhost:8080/topics/1"
}
}
}
The issue I have is that I am unable to get a handle on individual objects in a collection because SDR not only hides ids for all entities but also does not provide a 'self' link for inlined entities.
I don't want to simply PUT the whole aggregate because inline with DDD I want to handle changes of state via dedicated 'controller' resources, allowing the raising of event to trigger additional business logic. Consider adding/removing/updating a post comment in the example above.
I'm left with an number of options none of which I really like.
Reverse all my unidirectional relationships and create repositories for all the child entities, effectively abandoning the DDD aggregate design concept.
Move to bi-directional relationships, create repositories for all child entities and compose the aggregate using a Projection. The general advice from the internet (including SDR developer Oliver Gierke) is to avoid bi-directional relationships if at all possible due to performance considerations and having to manually manage the relationship.
Add a GUID or some other immutable unique identifier to the child entities. This feels wrong considering the whole point of HATEOAS is that the URI is the identifier. Even this breaks down when dealing with children of children.
I'm currently feeling inclined towards 2 as it seems to be the only workable option that allows me to retain the design principle.
Has anyone encountered and overcome a similar problem?
Edit:
I've come up with a possible solution:
Move to bi-directional relationships without creating repositories for child entities. This will give me the parents key so that I can compose a 'self' & other links using a ResourceProcessor e.g /topics/1/posts/add-post which I can handle via a RestController. This should work well enough at 1 level deep, it may have performance implications for deeper nesting e.g. /topics/1/posts/1/comments/add-comment as with JPA there's going to be a cost associated with doing the lookups to traverse the parent relationships. This would be done in tandem with #Alan Hay's solution to exposing Id's where there is no natural key in the entity.
This approach maintains DDD & HATEOAS at the cost of going against advice on bi-directional relationships.
Thoughts?
It is possible to add _links to resources that are not mapped through repositories. To add an action deleteComment, for instance, you should configure a #Bean like this:
#Bean
public ResourceProcessor<Resource<Comment>> commentProcessor() {
return new ResourceProcessor<Resource<Comment>>() {
#Override
public Resource<Comment> process(Resource<Comment> resource) {
resource.add(linkTo(methodOn(MyCustomController.class).deleteComment(resource.getContent().getId())).withRel("deleteComment"));
return resource;
}
};
}
You should get the link of the action on the Comment object inside the Post

Improving the design of a JPA polymorphic association

I have the following JPA entity hierarchy:
Upon logging in to the application a user has an instance of UserAccount in session; then depending on the concrete type of the organization associated to that UserAccount (Admin, Business or Family), a different dashboard/screen is displayed to the user e.g. if the user is a Business, then the dashboard for that business is displayed.
My concern with that design is that I have to do a instanceof check each time a user logs in so that I know which type of dashboard to display. I could also avoid that instanceof check by having a property in UserAccount such as organizationType (which would take one of three values) but then there would be redundant information.
Is there a way to improve my design? If so how?
Be greedy and get both, without redundancy.
Depending on the inheritance strategy, you may already have the organizationType info and you can expose it for free.
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "DTYPE")
public abstract class AbstractOrganization implements Serializable
{
#Id
protected Long id;
#Column(name = "DTYPE", insertable = false, updatable = false)
protected String organizationType;
...
}
the same applies also to the JOINED strategy.
Do not implement the setOrganizationType method.
Since a discriminator is required for simulating hierarchies with tables (except TABLE_PER_CLASS strategy), there's no redundancy and JPA provider will handle this attribute for you.

JPA same table with two implementing classes

I have an entity Product which contains another entity Category.
public class Product implements Serializable {
...
private Category category;
}
However, mobile products need a special kind of category.
public class MobileProduct extends Product implements Serializable {
...
private MobileCategory mobileCategory;
}
It makes sense to make MobileCategory inherit Category because in this case you won't need two classes for products but if you want to create queries using MobileCategory attributes, JPA may not allow that. If you choose to have two classes with a inheritance relationship, you are using exactly the same table with exactly the same attributes but with two implementing classes.
Which approach should I choose?

How to design many-to-many relationship in JPA entities?

I am trying to understand what would be the better way to design 2 entities which has many-to-many relationship? In database there will be a connecting table between these two entities. But do i have to follow the same approach while creating my entities?
For example: User to User group
A user may belong to many group and a group may contain many user.
In relational database I will have 3 table like User, User2Group, Group
So when I am creating my JPA entities, should I have 3 entities for 3 table or just 2 entities by providing the proper annotation(#ManytoMany).
Since I am new to JPA, I am trying to understand good and bad side from following point of view:
Performance
Code maintenance
Thanks, you input will be greatly appreciated.
No, you don't need to map the join table as an entity. Just use the ManyToMany annotation:
public class User {
...
#ManyToMany
private Set<Group> groups;
}
public class Group {
...
#ManyToMany(mappedBy = "groups")
private Set<User> users;
}
You would only need to map the join table as an entity if it was not a pure join table, i.e. if it had additional information like, for example, the date when the user entered in the group.
The mapping has little incidence on the performance. What is important is how you use and query the entities, and how the database is designed (indices, etc.)

JPA 2.0 retrieve entity by business key

I know there have been a number of similar posts about this, but I couldn't find a clear answer to my problem.
To make it as simple as possible, say I have such an entity:
#Entity
public class Person implements Serializable {
#Id
private Long id; // PK
private String name; // business key
/* getters and setters */
/*
override equals() and hashCode()
to use the **name** field
*/
}
So, id is the PK and name is the business key.
Say that I get a list of names, with possible duplicates, which I want to store.
If I simply create one object per name, and let JPA make it persistent, my final table will contain duplicate names - Not acceptable.
My question is what you think is the best approach, considering the alternatives I describe here below and (especially welcome) your own.
Possible solution 1: check the entity manager
Before creating a new person object, check if one with the same person name is already managed.
Problem: The entity manager can only be queried by PK. IS there any workaround Idon't know about?
Possible solution 2: find objects by query
Query query = em.createQuery("SELECT p FROM Person p WHERE p.name = ...");
List<Person> list = query.getResultList();
Questions: Should the objects requested be already loaded in the em, will this still fetch from database? If so, I suppose it would still be not very efficient if done very frequently, due to parsing the query?
Possible solution 3: keep a separate dictionary
This is possible because equals() and hashCode() are overridden to use the field name.
Map<String,Person> personDict = new HashMap<String,Person>();
for(String n : incomingNames) {
Person p = personDict.get(n);
if (p == null) {
p = new Person();
p.setName(n);
em.persist(p);
personDict.put(n,p);
}
// do something with it
}
Problem 1: Wasting memory for large collections, as this is essentially what the entity manager does (not quite though!)
Problem 2: Suppose that I have a more complex schema, and that after the initial writing my application gets closed, started again, and needs to re-load the database. If all tables are loaded explicitly into the em, then I can easily re-populate the dictionaries (one per entity), but if I use lazy fetch and/or cascade read, then it's not so easy.
I started recently with JPA (I use EclipseLink), so perhaps I am missing something fundamental here, because this issue seems to boil down to a very common usage pattern.
Please enlighten me!
The best solution which I can think of is pretty simple, use a Unique Constraint
#Entity
#UniqueConstraint(columnNames="name")
public class Person implements Serializable {
#Id
private Long id; // PK
private String name; // business key
}
The only way to ensure that the field can be used (correctly) as a key is to create a unique constraint on it. You can do this using #UniqueConstraint(columnNames="name") or using #Column(unique = true).
Upon trying to insert a duplicate key the EntityManager (actually, the DB) will throw an exception. This scenario is also true for a manually set primary key.
The only way to prevent the exception is to do a select on the key and check if it exists.