Lifecycle event model of PlayMorphia and Morphia
The content of this chapter is only valid for PlayMorphia v1.2.4 or later.
In this chapter we will explorer the lifecycle event model of PlayMorphia (start from v1.2.4) and Morphia.
Create events
PlayMorphia create events
event | description |
---|---|
on add | triggered before an new entity is saved |
added | triggered after an new entity is saved |
Event implementation
event | annotation | interface |
---|---|---|
on add | @OnAdd | IMorphiaEventHandler.onAdd(Model) |
added | @Added | IMorphiaEventHandler.added(Model) |
Morphia create events
Morphia does not provide specific create events, however you could use PrePersist
, PreSave
and PostPerist
to simulate create events and use this.isNew()
to identify if current model instance is an new entity or existing entity. See Morphia update events for detail about PrePersist
, PreSave
and PostPerist
events.
Update events
PlayMorphia update events
event | description |
---|---|
on update | triggered before an existing entity is saved |
updated | triggered after an existing entity is saved |
Event implementation
event | annotation 1 | interface 2 |
---|---|---|
on update | @OnUpdate | IMorphiaEventHandler.onUpdate(Model) |
updated | @Updated | IMorphiaEventHandler.updated(Model) |
1 see more about annotation based PlayMorphia lifecycle event handling
2 see more about event handler based PlayMorphia lifecycle event handling
Morphia update events
event | annotation | description |
---|---|---|
pre persist | @PrePersist | triggered before a PlayMorphia model instance get converted into a MongoDB’s DBObject |
pre save | @PreSave | triggered after a PlayMorphia model instance get converted into a MongoDB’s DBObject and before that DBObject is saved into MongoDB |
post persist | @PostPersist | triggered after the model instance saved into MongoDB |
Morphia annotation enable you do define methods that accept parameters and return result. Click here for examples.
Load events
PlayMorphia load events
event | description |
---|---|
on load | triggered before an entity is loaded from MongoDB |
loaded | triggered after an entity is loaded from MongoDB |
OnLoad
event is seldom used as when this event triggered, the entity is still empty and waiting for the fields to be filled
Event implementation
event | annotation | interface |
---|---|---|
on load | @OnLoad | IMorphiaEventHandler.onLoad(Model) |
loaded | @Loaded | IMorphiaEventHandler.loaded(Model) |
Morphia load events
event | annotation | description |
---|---|---|
pre load | @PreLoad | triggered before a PlayMorphia model instance get loaded from MongoDB |
post load | @PostLoad | triggered after the model instance loaded from MongoDB |
Delete events
PlayMorphia delete events
event | description |
---|---|
on delete | triggered before an entity is removed from MongoDB |
deleted | triggered after an entity deleted from MongoDB |
Event implementation
event | annotation | interface |
---|---|---|
on delete | @OnDelete | IMorphiaEventHandler.onDelete(Model) |
deleted | @Deleted | IMorphiaEventHandler.deleted(Model) |
Morphia delete events
Morphia does not support delete events
Batch delete events
PlayMorphia batch delete events
event | description |
---|---|
on batch delete | triggered before a set of entities defined by a PlayMorphia query removed from MongoDB |
batch deleted | triggered after a set of entities defined by a PlayMorphia query deleted from MongoDB |
Event implementation
event | annotation | interface |
---|---|---|
on batch delete | @OnBatchDelete | IMorphiaEventHandler.onBatchDelete(MorphiaQuery) |
batch deleted | @BatchDeleted | IMorphiaEventHandler.batchDeleted(MorphaQuery) |
Morphia batch delete events
Morphia does not support batch delete events
Additional notes
PlayMorphia annotated lifecycle event handler signature
No return object and method parameters should be defined for the following annotation based event handler: @OnLoad, @Loaded, @OnAdd, @Added, @OnUpdate, @Updated, @OnDelete, @Deleted
:
@Entity MyMode extends Model {
// correct signature
@OnLoad void onLoad() {}
@Loaded void loaded() {}
@OnAdd void onAdd() {}
@Added void added() {}
@OnUpdate void onUpdate() {}
@Updated void updated() {}
@OnDelete void onDelete() {}
@Deleted void deleted() {}
// the following method's signatures are not correct and they will not be triggered at all
@OnLoad Model myOnLoad() {...}
@Loaded void myLoaded(String xx) {...}
@OnAdd String myOnAdd(Model xx) {...}
}
You could make those methods static or non-static, but it’s highly recommend to use non-static methods for the above event handling as you get the access to the entity which is experiencing the lifecycle events via “this” pointer.
There is completely no requirements on method scope, you can make it either one of “public”, “protected”, “private” or default package level, the functionality will not impact by changing the method scope.
Unlike the above events, the two batch events (@OnBatchDelete
and @BatchDeleted
) have a bit different method signature:
@Entity MyModel extends Model {
@OnBatchDelete static void onBatchDelete(MorphiaQuery q) {...}
@BatchDeleted static void BatchDeleted(MorphiaQuery q) {...}
}
As you could see, we have 2 differences in the batch event handler definition compare to that of the other event handlers:
- A MorphiaQuery type parameter is required. This is mandatory, otherwise your method will not be called when the batch delete event triggered.
- the batch event handling methods are defined as static methods. This is optional but recommended practice.
There are different method signature requirements when you are writing Morphia annotation marked lifecycle event handlers, please refer to this page for detail.
More on BatchDeleted
event
A common error is to use the MorphiaQuery
argument passed into BatchDeleted
event handler to query for which models has been deleted. However that will always return an empty list as all those entities has been removed from MongoDB already. One way to get the deleted entities is to remember them in the OnBatchDelete
event handler:
@Entity MyModel extends Model {
private Map<MorphiaQuery, List<MyModel>> deleteModels_ = new HashMap<MorphiaQuery, List<MyModel>>();
@OnBatchDelete static void onBatchDelete(MorphiaQuery q) {
List<MyModel> list = q.asList();
deleteModels_.put(q, list);
}
@BatchDeleted static void batchDeleted(MorphiaQuery q) {
List<MyModel> list = deleteModels_.get(q);
// do whatever you want on the deleted models
...
}
}
Why do you prefer PlayMorphia event handling framework to Morphia one
- More clear. PlayMorphia events distiguish between add (new) and update (existing) entities while Morphia events don’t
- Performance. There are very little performance gain if you choose PlayMorphia event handling model. PlayMorphia code enhancer will burn the relevant code into final byte code so at runtime there is no reflection at all. While Morphia needs one time reflection for event handler call and then cache it to hash map for later on calls.
- More complete. PlayMorphia support delete and batch delete events while Mophia doesn’t.
Performance consideration
You are NOT required to do the same thing as shown in the above code. Calling to the event handler methods is executed in the current thread, the more logic you put into the event handlers the more performance is impact. So please do as simple as possible in any of the event handlers. Implement only the logic you need. If you don’t need to bother with batch delete events then you shouldn’t add batch delete event handler. Actually in most cases you don’t need to implement any lifecycle event handlers. This is ture for both PlayMorphia and Morphia event handling model.