Search code examples
javamongodbmorphianosql

Java: Enforce static method from super class (Mongo/Morphia context)


I'm designing the architecture for a ODM in Java. I have a hierarchal structure with a top-level abstract Document class. Implementations of DB objects will extend this class.

public abstract class Document {
    ObjectId id;
    String db;
    String collection;
}

public class Student extends Document {
    db = "School";
    collection = "Student";

    String name;
    int age;
    float gpa;
}

I want each class to be able to statically fetch results for its associated collection. For example, I'd like to do something like Students.get(Students.class, new ObjectId(12345)) which would return a Student from the database. Note that I need to specify the class in the get() method, this is a restriction of the object mapper library I'm using (Morphia).

What would be the best way to enforce each class to have this get() method? There are a couple constraints:

  1. get() should be implemented as a static method
  2. I'd like to avoid redundant code if possible and not have to specify the class for each implementation of get(). For example if I have a Student and Teacher class, I want to avoid specifying Students.class and Teacher.class manually. I'm not sure this is possible though, since get() is a static method.

I think this is a variation on the common abstract static Java problem, but I want to make sure I'm approaching it the right way first.


Solution

  • I assume your student class should look something like this:

    @Entity(name="Student")
    public class Student extends Document {
        protected String name;
        protected int age;
        protected float gpa;
        ...
    }
    

    Generic queries would something like this:

    public <E extends BaseEntity> E get(Class<E> clazz, final ObjectId id) {
        return mongoDatastore.find(clazz).field("id").equal(id).get();
    }
    

    Why would you want to make this static? You'd hard-code dependencies and break polymorphism; making it impossible to use a mock implementation for tests (which doesn't need a real database).