|
EntityAnnotation
Define your Entity
Entity AnnotationIf you want to store your class instance in Mongo via Morphia, the first thing you need to do is annotate your class as an @Entity: import com.google.code.morphia.annotations.Entity;
@Entity
public class Hotel {
...
}Name + ConstructorYou can also optionally set a name for your MongoDB DBCollection name. You will also need a (no-args) default constructor. @Entity("hotels")
public class Hotel {
...
public Hotel() {
}
...
}Note that your default constructor does not need to be public, it can also be protected or private. Class name in document and how to suppress itThe @Entity annotation provides another optional parameter to not store the class name in the document. @Entity(value="hotels", noClassnameStored=true)
public class Hotel {
...
public Hotel() {
}
...
}The default behavior is to store the class name in the document. Why would you need it? This is mainly used when storing different entities in the same collection and reading them back as the base or super class. Ex. @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(); As you can see, 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 to add the noClassnameStored=true parameter to the Entity annotation. @IdClasses annotated with @Entity require unique @Id values; these values are stored in the MongoDB "id" field, which has a unique index requirement. The Hotel class above would have: @Entity
public class Hotel {
@Id
private ObjectId id;
...
}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. @IndexedThis annotation applies an index to a field. The indexes are applied when the datastore.ensureIndexes() method is called... more on this below. You apply the Indexed annotation on the field you want indexed by MongoDB. @Entity
public class Product {
@Id
private ObjectId id;
@Indexed(value=IndexDirection.ASC, name="upc", unique=true, dropDups=true)
private String upcSymbol;
...
}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 Datastore.ensureIndexes() needs to be called to apply the indexes to MongoDB. The method should be called after you have registered your entities with Morphia. It will then synchronously create your indexes. This should probably be done each time you start your application. Note: Doing this on an existing system, with existing indexes and capped collections, should take no time (and do nothing). Morphia m = ... Datastore ds = ... m.map(Product.class); ds.ensureIndexes(); //creates all defined with @Indexed You can read more about MongoDB indexes here, http://www.mongodb.org/display/DOCS/Indexes EmbeddedYou can also choose to create a class that will be embedded in the Entity, we use the @Embedded annotation in this case. For example, the Hotel class above might have an Address. The Address would be an inseparable part of the Hotel, would not have its own ID, and would not be stored in a separate collection. In this case we would annotate the Address class as @Embedded:
@Entity
public class Hotel {
...
@Id
private ObjectId id;
@Embedded
private Address address;
...
}
...
@Embedded
public class Address {
...
}As you can see, classes with @Embedded annotation do not need an @Id. This is because they always be included in another class. In fact, they are not allowed to have an @Id if the class is annotated with @Embedded. | |
Hi team, it could be usefull to get a way to ignore an inherited field via annotation.
ie : one domain extends Observable, "change" and "obs" inherited fields could be marked "transient"
Amaury, some people might find that useful. Currently there is no support for that but it is relatively easy to add as an extension in your own code.
If you need more help or just want to ask for the feature, please file an issue (http://code.google.com/p/morphia/issues/list).
Hi, I have a collection that is stored by a different team, does not follow the class per collection rule, and does not have className in the document (instead it has a type enum which is sort of like a class name but won't work with morphia). It seems like morphia should be able to easily support an optional interface something like this:
The default implementation could be to lookup the className value in the DBObject and return a class for that, which means clients that have control over both sides don't do anything and don't have to know anything about a ConversionPolicy?. But peeps like me who are unfortunate can implement a custom ConversionPolicy? and still use morphia.
What do you think?
Morphia can save and load classes without default constructor. The trick is very simple
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); } };Is it possible to disable class name storage on embedded documents? If so, how?
Thank you Dmitry !! :)
I support Kevin's idea!