I hope this question is not opinion based, but here we go. I am developing a small API with spring boot, spring data jpa, and JWT Token as the authentication system. The API is pretty straightforward, is an exam generator, where you can register professor, course, question, choice etc.
For example: [13/11/2017 - edited to include AbstractEntity]
@MappedSuperclass
public class AbstractEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
protected Long id;
protected boolean enabled = true;
//equals, hashcode...
}
public class Professor extends AbstractEntity{
private String email;
}
public class Course extends AbstractEntity {
@ManyToOne(optional = false)
private Professor professor;
}
public class Question extends AbstractEntity {
@ManyToOne(optional = false)
private Course course;
}
Because the authentication system is JWT token for all queries I have to include the professor's information.
For example
public interface CourseRepository extends PagingAndSortingRepository<Course, Long> {
@Query("select c from Course c where c.id = ?1 and c.professor = ?#{principal.professor} and c.enabled = true")
Course findOne(Long id);
}
The problem is that for every crud query I will have to write my own custom query, because of professor's information and also the enabled field.
I know there is a way to extends the PagingAndSortingRepository and write your own custom query, like this:
public interface CustomPagingAndSortRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
@Override
@Query("select e from #{#entityName} e where e.id = ?1 and e.professor = ?#{principal.professor} and e.enabled = true")
T findOne(ID id);
//More fields overrided here
}
This CustomPagingAndSortRepository would work perfectly for all classes if I only had enabled to worry about. This class will work perfectly for Course because e.professor = ?#{principal.professor}
will find the Professor there. But it will not work for Question, for example, because I need a join with the course class to get the professor, like e.course.professor = ?#{principal.professor}
The point is f I put an association with Professor in all classes I can make that generic code work, save tons of code but sacrificing database design's normalization. The question is: Is there another way? or maybe is it valid to do it?
PS: The Question, Course etc will never change owner, it means that only the Professor who created will be able to use it.