1. In java the default attribute for annotations can be used without a name. The name of the default attribute is always value . Any time you see @MyAnnotation("arg") it can be re-written as @MyAnnotation(value = "arg") , and must be if you add additional attributes.
2. @Entity Marks entities to be stored directly in a collection. This annotation is optional in most cases. There is no harm in including it to be more verbose, and make clear the intention for the class.
3. You can optionally set a name for your MongoDB DBCollection name. You will also need a (no-args) default constructor(it’s not necessarily public):
@Entity("hotels") public class Hotel { ... public Hotel() { } ... }
4. The @Entity annotation provides another optional parameter to not store the class name in the document:
@Entity(value="hotels", noClassnameStored=true)
The default behavior is to store the class name in the document. This is mainly used when storing different entities in the same collection and reading them back as the base or super class:
@Entity("animals") abstract class Animal { String name; } @Entity("animals") Cat extends Animal { ... } @Entity("animals") Dog extends Animal { ... } //And then performing the following query... List<Animal> animals = ds.createQuery(Animal.class).asList();
Without the class name stored in the document, Morphia wouldn't know which class to actually create. If you are only storing a single entity type in the collection and you are concerned about datasize, it would be safe not to store the classname.
5. Classes annotated with @Entity require unique @Id values; these values are stored in the MongoDB "id" field, which has a unique index requirement. Mongo will generate the Id for your new objects, so you don't need to worry about that. It will be stored as an ObjectId ; If you use any other type than ObjectId you must set the value yourself.
6. @Indexed applies an index to a field. The indexes are applied when the datastore.ensureIndexes() method is called:
@Indexed(value=IndexDirection.ASC, name="upc", unique=true, dropDups=true)
The parameters are:
value : Indicates the direction of the index; IndexDirection.ASC (ascending), IndexDirection.DESC (descending), IndexDirection.BOTH (both), default is ascending
name : The name of the index to create; default is to let the mongodb create a name (in the form of key1_1/-1_key2_1/-1...
unique : Creates the index as a unique value index; inserting duplicates values in this field will cause errors, default false
dropDups : Tells the unique index to drop duplicates silently when creating; only the first will be kept. default false.
7. Morphia can save and load classes without default constructor:
morphia.getMapper().getOptions().objectFactory=new DefaultCreator() { @Override public Object createInstance(Class clazz, com.mongodb.DBObject dbObj) { if(clazz.equals(ThirdPartyClass.class)) { return new ThirdPartyClass(dbObj.get("something_required")); } return super.createInstance(clazz,dbObj); } };
8. You can also choose to create a class that will be embedded in the Entity, we use the @Embedded to annotate the embedded field in the Enity and the class for that field. The class annotated with @Embedded is not allowed to have an @Id .
9. In addition to being able to declare an index on a single field you can also declare the indexes at the class level. This allows you to create compound indexes with multiple fields:
@Entity // this is require to know where the indexes are to be created @Indexes({ @Index("user, -cs"), @Index("changedRecord, -cs")}) public class ChangeLog{ Date date; String user; Record changedRecord; }
10. Those fields tagged with @Transient will not be persisted. Those fields tagged with @Serialized will be converted to binary, and persisted. Those fields tagged with @NotSaved will not be saved, but can be loaded. Those fields tagged with @AlsoLoad can be loaded as any of the supplied names.
11. A field tagged with @Version is to control optimistic locking for the containing entity. If the versions change while modifying an entity a ConcurrentModificationException will be throw in the write method (save/delete/etc). This field will be automatically managed for you -- there is no need to set a value and you should not do so anyway :
@Entity class Myclass { ... @Version Long v; }
12. @Reference marks fields as stored in another collection and which are linked (by a dbref reference field). When the Entity is loaded, so is the (direct) reference. It supports following attribute:
a) lazy : Instead of loading the referenced field with the Entity, it will be lazily loaded on the first method call of the proxy instance.
b) ignoreMissing : When loading bad references won't generate an exception.
c) concreteClass : The class type to create for these references.
13. The referenced object must have been saved in Mongo before saving the object referencing it.
14. There are various annotations which can be used to register callbacks on certain lifecycle events. These include Pre/Post-Persist (Save), and Pre/Post-Load.
a) @PrePersist - Called before save, it can return a DBObject in place of an empty one.
b) @PostPersist - Called after the save call to the datastore
c) @PreLoad - Called before mapping the datastore object to the entity (POJO); the DBObject is passed as an argument (you can add/remove/change values)
d) @PostLoad - Called after mapping to the entity
15. All parameters and return values are options in your implemented callbacks.
16. Here is a simple example of an entity that always saves the Date it was last updated at:
class BankAccount { @Id String id; Date lastUpdated = new Date(); @PrePersist void prePersist() {lastUpdated = new Date();} }
17. You can separate the lifecycle event implementation in an external class, or many:
@EntityListeners(BackAccountWatcher.class) class BankAccount { @Id String id; Date lastUpdated = new Date(); } class BankAccountWatcher{ @PrePersist void prePersist(BankAccount act) {act.lastUpdated = new Date();} }
18. There is no way to support a Delete lifecycle event.
19. By default, Morphia will try to map all the supported basic and primitive types to/from Mongo. MongoDB only has the following data types:
a) Integer (32-bit signed value)
b) Long (64-bit signed value)
c) Double (64-bit IEEE754 fp value)
d) String
20. Morphia can also store a java.util.List , java.util.Set , and java.util.Map collections, and primitive arrays of any supported types. Morphia will use the following implementations (by default) when creating collections:
a) java.util.ArrayList for List
b) java.util.HashSet for Set
c) java.util.HashMap for Map
If you want to use another implementation, you can override this by the concreteClass attribute of @Property /@Embedded /@Reference annotations.