This syntax is only available for GAE implementation for the time being but will be ported soon to other impl
The following code samples can be found in samples dir
This is a new syntax to represent:
- the relation from the owner/aggregator entity to the child/owned entity in an One2XXX relation
- the owner side in an owned relation
- the aggregator side in an aggregated relation
Keep in mind that Siena just manages the relation but not the objects themselves
- manage the relation but not the full life-cycle of related entities.
- manage relation change from one related entity to another one.
- auto-insert the related entity at the same time as the parent (or when updating it) if not done yet.
- lazy-load the related entity only when required.
- delete-cascade the aggregated entities because an aggregated entity can’t exist outside its aggregator. This is the ONLY accepted delete cascade.
- manage the updates of data within the related entity. You must save it yourself.
- delete the owned entities when you delete the owner since an owned entity can change owner.
Here is the owner model:
public class OwnerModel {
...
@Owned(mappingBy="owner")
public One<ChildModel> child;
...
}
Here is the child model:
public class ChildModel {
...
public OwnerModel owner;
...
}
Note On the child side, the owner field is just written as a simple reference to the owner without any One<T>
. Why? because, on the owned entity side, the owner is just referenced by its id/key.
Using the old notation Query<T>
, the One<T>
is equivalent to:
public class OwnerModel {
...
@Filter("owner")
public Query<ChildModel> child;
...
}
Note Yet, you should take care of the unicity of the child by yourself.
Here is the aggregator model:
public class AggregatorModel {
...
@Aggregated
public One<ChildModel> child;
...
}
Here is the aggregated model:
public class AggregatedModel {
...
...
}
Note On the aggregated side, there is no reference to the aggregator because an aggregated entity shall not be aware of its aggregator: it’s a part of it but it was not necessarily meant to be.
It’s very useful because you don’t need to foresee your model will be aggregated while designing it and you can aggregate any model.
The aggregator reference is managed by Siena itself and you don’t have to deal with it neither declare it in your model.
Note Nevertheless, if you absolutely want to access your own aggregator, it’s possible. Go to the aggregated relation page.
The 3 importants functions of One<T>
are:
void set(T obj)
: a setter to change the OneToXXX related childT get()
: a getter to get the current child of the OneToXXX relationOne<T> forceSync()
: a useful function to force to resynchronization of the child with the DB when you want to be sure you get the latest version.
Dog pluto = new Dog("Pluto");
Person tom = new Person("Tom"); // associates the child entitys tom.dog.set(pluto); tom.save(); // or insert(), it's exactly the same behavior
Note You don’t have to insert the child object as Siena inserts it at the same time as the parent (if the child was not inserted yet).
Person tom = Person.getByName("Tom");
// here tom's dog is not yet loaded and you can load it through One<T>.get()
Dog pluto = tom.dog.get();
Note tom.dog is a One<Dog>
so you need to use get()
to access the real object
Person tom = Person.getByName("Tom"); // creates a new dog Dog medor = new Dog("Medor"); // associates the new dog to the master tom.dog.set(medor); // inserts medor, changes the relation and updates tom tom.update();
// OWNED RELATION ONLY: proves pluto is no more the dog of tom Dog pluto = Dog.getByName("Pluto"); assert(pluto.master == null);
Note In an aggregated relation, when you change the target of the relation and updates the parent, the previous related entity is deleted as it can’t exist outside its parent aggregator.
Person tom = Person.getByName("Tom");
// gets current pluto
Dog pluto = tom.dog.get();
...
// some time later, you want to be sure to have the latest version
Dog pluto = tom.dog.forceSync().get();
Person tom = Person.getByName("Tom"); Dog pluto = tom.dog.get(); pluto.name = "Pluto2";
tom.save(); // THIS DOESN'T UPDATE PLUTO assert(pluto.name.equals("Pluto")); pluto.save(); // THIS SAVE PLUTO assert(pluto.name.equals("Pluto2"));
Car peugeot = Car.getByName("Peugeot"); Motor motor = car.motor.get(); Motor newmotor = new Motor("newmotor"); car.motor.set(newmotor);
peugeot.update(); // motor is also deleted motor.get(); // throws SienaException()
Car peugeot = Car.getByName("Peugeot"); Motor motor = car.motor.get();
peugeot.delete(); // motor is also deleted