-
Notifications
You must be signed in to change notification settings - Fork 8
TransparentActivationExamples
package com.db4odoc.ta.example;
import com.db4o.Db4oEmbedded;
import com.db4o.ObjectContainer;
import com.db4o.config.EmbeddedConfiguration;
import com.db4o.query.Predicate;
import com.db4o.ta.TransparentActivationSupport;
import com.db4o.ta.TransparentPersistenceSupport;
import java.io.File;
public class TransparentActivationExamples {
private static final String DATABASE_FILE_NAME = "database.db4o";
public static void main(String[] args) {
transparentActivationExample();
transparentPersistenceExample();
}
private static void transparentActivationExample() {
cleanUp();
// #example: Transparent activation in action
{
ObjectContainer container = openDatabaseWithTA();
Person person = Person.personWithHistory();
container.store(person);
container.close();
}
{
ObjectContainer container = openDatabaseWithTA();
Person person = queryByName(container,"Joanna the 10");
Person beginOfDynasty = person.getMother();
// With transparent activation enabled, you can navigate deeply
// nested object graphs. db4o will ensure that the objects
// are loaded from the database.
while(null!=beginOfDynasty.getMother()){
beginOfDynasty = beginOfDynasty.getMother();
}
System.out.println(beginOfDynasty.getName());
container.close();
}
// #end example
cleanUp();
}
private static void transparentPersistenceExample() {
cleanUp();
// #example: Transparent persistence in action
{
ObjectContainer container = openDatabaseWithTP();
Person person = Person.personWithHistory();
container.store(person);
container.close();
}
{
ObjectContainer container = openDatabaseWithTP();
Person person = queryByName(container,"Joanna the 10");
Person beginOfDynasty = person.getMother();
// With transparent persistence enabled, you can navigate deeply
// nested object graphs. db4o will ensure that the objects
// are loaded from the database.
while(null!=beginOfDynasty.getMother()){
beginOfDynasty = beginOfDynasty.getMother();
}
System.out.println(beginOfDynasty.getName());
// Updating a object doesn't requires no store call.
// Just change the objects and the call commit.
beginOfDynasty.setName("New Name");
container.commit();
container.close();
}
{
ObjectContainer container = openDatabaseWithTP();
Person person = queryByName(container,"New Name");
// The changes are stored, due to transparent persistence
System.out.println(person.getName());
container.close();
}
// #end example
cleanUp();
}
private static void cleanUp() {
new File(DATABASE_FILE_NAME).delete();
}
private static Person queryByName(ObjectContainer container,final String name) {
return container.query(new Predicate<Person>() {
@Override
public boolean match(Person o) {
return o.getName().equals(name);
}
}).get(0);
}
private static ObjectContainer openDatabaseWithTP() {
// #example: Activate transparent persistence
EmbeddedConfiguration configuration = Db4oEmbedded.newConfiguration();
configuration.common().add(new TransparentPersistenceSupport());
ObjectContainer container = Db4oEmbedded.openFile(configuration, DATABASE_FILE_NAME);
// #end example
return container;
}
private static ObjectContainer openDatabaseWithTA() {
// #example: Activate transparent activation
EmbeddedConfiguration configuration = Db4oEmbedded.newConfiguration();
configuration.common().add(new TransparentActivationSupport());
ObjectContainer container = Db4oEmbedded.openFile(configuration, DATABASE_FILE_NAME);
// #end example
return container;
}
}using Db4objects.Db4o.TA;
var cf = Db4oEmbedded.NewConfiguration();
cf.Common.Add(new TransparentActivationSupport());
cf.Common.Add(new TransparentPersistenceSupport());
using (var oc = Db4oEmbedded.OpenFile(cf,path)){}In order to use transparent persistence we need to configure it first:
After that transparent persistence is active and manages the activation and updates for us.
Transparent persistence also manages updates. You just can change existing objects as you please. Later when you commit the transaction all updates are persisted. You don't need to store objects in order to update them. You only need to call store once for objects which are new and are not referenced by an existing object.
Activation is a mechanism which controls object instantiation. Why is this necessary? Let's look at an example. We store person-objects with its parents. Each person object has a reference to his parents, the parents again have references to their parents and so on and so forth. Now we load a person object from the database, what does db4o do? Does it load the person object, its parents and the parents of the parents? Then it probably loads all objects from the database and will use up all memory.
Luckily db4o does not behave like this. When a query retrieves objects, their fields are loaded into memory (activated in db4o terms) only to a certain activation depth. In this case depth means "number of member references away from the original object". All the fields beyond the activation depth are set to null or to default values.So db4o does not load the whole object graph at once. Instead, db4o loads only the parts which we are interested in.
Let's see db4o's activation in action. To do so we need a deep object-graph. We create a person class with a mother-field and then create a deep hierarchy of people, for example a hierarchy of seven people.
After that we close the database, reopen it and query for a person. Then we start to traverse the object graph. At a certain point we will reach objects which aren't activated anymore. In those objects all fields are null or have the default value:
Since not activate objects have set all their fields to null, they can cause null pointer exceptions:
We've seen that activation can cause issues and we have to deal with it. There are different strategies for that.
We can explicitly activate objects or ask about their activation state. This way we can activate objects when needed. However as soon as we need to activate objects explicitly all over the place in our code we should look for alternatives.
Alternatively we can increase the activation depth globally or for certain types. However we need to be aware that a high activation depth decreases performance. That's why we should be very careful with increasing the activation depth.
We can even more fine tune the activation depth. However the fundamental issue is the same. When we increase the activation depth it will hurt performance.
The last option we have is transparent activation. Transparent activation takes care of all activation issues. It activates objects as soon as they are needed. To get transparent activation we need to enhance our classes at compile time. Read this section of the tutorial where we use transparent activation.