问题
I'm not sure if its the way Morphia is designed but here it goes...
Student.class (methods omitted)
@Entity(value = "students", noClassnameStored = true)
public class Student
{
@Id
private String id = new ObjectId().toString();
private String name;
private String city = "London"; // Default Value
}
NOTE: That I have assigned a DEFAULT value to Instance variable city
.
Now the code...
Student s1 = new Student("James Bond"); // London IS his default city
ds.save(s1);
Student s2 = new Student("Jason Bourne");
s2.setCity("New York"); // Set a city for Mr. Bourne
ds.save(s2);
System.out.println("----- Normal -----");
List<Student> studentsNormal = ds.createQuery(Student.class).asList();
for(Student s: studentsNormal)
System.out.println(s);
System.out.println("----- Projected -----");
Query<Student> query = ds.find(Student.class);
query.retrievedFields(false, "city");
List<Student> studentsProjected = query.asList();
for(Student s: studentsProjected)
System.out.println(s);
And, now the output...
----- Normal -----
Student{id='57337553db4f0f0f10a93941', name='James Bond', city='London'}
Student{id='57337553db4f0f0f10a93942', name='Jason Bourne', city='New York'}
----- Projected -----
Student{id='57337553db4f0f0f10a93941', name='James Bond', city='London'}
Student{id='57337553db4f0f0f10a93942', name='Jason Bourne', city='London'}
Now, 4 questions about the Morphia behaviour...
Q1. For Mr. Bond, I did not change the city
and excluded city
from the projected list, yet the default value of the city
is printed as London
. Should'nt this be null?
Q2. For Mr. Bourne, I did change the city
to New York
but still during the projection, it picked up the default value and showed London
. Should'nt this be null as well?
I havent yet seen the Projection.class from Morphia (intend to do so tonight) but it seems that for exclusions, Morphia seems to pick up the default value and does not over-ride with null
. Now this becomes a hindrance since I do not have any way to provide default value to my Instance Variables without exposing them to client's...
Q3. Is this Morphia or a MongoD Java Driver behavior/issue?
And the final question...
Q4. Any known workaround for this?
I have googled around but did not come around any solution or explanation so far...
Thanks in advance...
SG
回答1:
When Morphia is reading your documents from the query results, the first thing it does is create a new instance of your entity, Student
. It just invokes the no argument constructor. There's no magic involved. The city field is initialized with a value. Once that's done, Morphia will take each key in the document returned from the database, find that mapped field, and set it. In your case, there is not city key in the document and so that field is never set by Morphia leaving the initialized value in place.
In general, initializing fields on entities like this is a bad practice. For every entity loaded from the database, the JVM has to initialize those fields to some value only to overwrite them later. In cases such as yours where certain fields don't come back in a query result, those values remain after Morphia returns the new instances back to your application.
来源:https://stackoverflow.com/questions/37170629/morphia-projection-behavior-for-instance-variable-with-default-value