I
- type of the persistent object and transport object id. This type
should be immutable. It is critical this type implements equals()
and hashCode() correctly.P
- type of the persistent object.T
- type of the transport object with a reference to the owner.Q
- type of the transport object with a reference to the owner's id.F
- type of the associated filter.S
- type of the associated sort specification type.E
- type of the owner persistent object and owner transport object
id. This type should be immutable. It is critical this type
implements equals() and hashCode() correctly.W
- type of the owner persistent object.R
- type of the owner transport object.public abstract class AbstractBidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>> extends AbstractBaseDao<I,P,T,F,S> implements BidirectionalDependentDao<I,P,T,Q,F,S,E,W,R>
One to Many Relations with Dependent Entities
Note that any other type of relation (One to many or many to many with
independent entities) could be implemented using Dao
s.
Item
be a model object.Image
be a model object.Item
has a collection of Image
. Dependent classes are
modeled as value type (Collection of value type).ItemEntity
be a storable.ItemImageEntity
be the dependent storable. The dependent
object has no life outside of the collection; it's dependent on an
Item
entity.Dao
may be used to access ItemEntity
.Item
to Image
is
unidirectional then the same regular Dao
that
access ItemEntity
could also access ItemImageEntity
. No
need of a separated DAO for ItemImageEntity
since JPA will
propagate updates when the collection of dependent entities is modified.
The Dao
will just need to create an ItemImageEntity
from
Image
and vice-verza. With an unidirectional relation you can
navigate to the images by accessing the collection through an item
instance. This is the only way you can get the images objects; no
other entity holds a reference to them (dependent entity value
type).Item
to Image
is
bidirectional a BidirectionalDependentDao
should
be used to access ItemImageEntity
. In a bidirectional relation it
is possible to navigate from an Image
back to an Item
. Note
this type of navigation does not make much sense and should be avoided if
possible. The JPA provider (Like Hibernate) can fill in this property for
you if you annotate your entity accordingly. True bidirectional
navigation is impossible with JPA, however. You can't retrieve an
ItemImageEntity
independently and then navigate back to its parent
ItemEntity
. This is an important issue: You can load
ImageEntity
instances by querying for them. But these images won't
have a reference to their owner (the property is null). For this reason
this implementation introduces Dependable
to keep a reference of
the owner's id so it can be manually retrieved (Since JPA provider won't
fill the owner if the dependent object is queried by itself). Annotations Examples:
One to many association in the independent object
@OneToMany(cascade=CascadeType.ALL, mappedBy="owner", orphanRemoval=true) private Collection<ItemImageEntity> images = new ArrayList<ItemImageEntity>();One to many association in the dependent object
@ManyToOne
@JoinColumn(name = "owner_fk")
private ItemEntity owner;
// Needed to implement true bidirectional navigation. See Dependable
note above.
@Column(name = "owner_id")
private Long ownerId;
Modifier | Constructor and Description |
---|---|
protected |
AbstractBidirectionalDependentDao(Class<P> entityClass)
Construct DAO and initialize query predicate generator.
|
protected |
AbstractBidirectionalDependentDao(Class<P> entityClass,
UpdateStrategy<P,T> updateStrategyT,
UpdateStrategy<P,Q> updateStrategyQ)
Construct DAO and initialize query predicate generator.
|
Modifier and Type | Method and Description |
---|---|
protected abstract void |
conformQ(P target,
Q source)
Synchronizes the transport object and the persistent object state.
|
protected abstract void |
conformT(P target,
T source)
Synchronizes the transport object and the persistent object state.
|
Q |
convert(P source)
Converts an instance of type S to an instance of type T
|
T |
convert(P storable,
BaseDao<E,W,R,?,?> ownerDao,
Converter<W,R> ownerConverter,
DataStoreContext context)
Converts the storable object to a transportable.
|
T |
convert(P source,
R owner)
Converts the storable object to a transportable.
|
P |
create(T transportable,
W owner,
DataStoreContext context)
Creates a new persistent object with the data from the given transport
object.
|
protected abstract P |
createStorableInstance(T transportable,
W owner)
Creates the instance of the persistent object (Entity).
|
protected abstract Q |
doConvert(P source)
Converts the persistent object to a transport object.
|
protected abstract T |
doConvert(P source,
R owner)
Converts the persistent object to a transport object.
|
protected abstract T |
findDependent(I dependentId,
R owner)
Finds a dependent with the given id.
|
void |
update(P target,
T source,
DataStoreContext context)
Updates the persistent object related to the given transport object.
|
P |
update(Q transportable,
DataStoreContext context)
Updates the persistent object related to the given transport object.
|
count, find, find, findAll, get, getQueryPredicate, getQueryPredicateGenerator, getSingularAttribute, updateDependents
protected AbstractBidirectionalDependentDao(Class<P> entityClass)
entityClass
- persistent object class.protected AbstractBidirectionalDependentDao(Class<P> entityClass, UpdateStrategy<P,T> updateStrategyT, UpdateStrategy<P,Q> updateStrategyQ)
entityClass
- persistent object class.updateStrategyT
- update strategy for the transport object with a
reference to the owner.updateStrategyQ
- update strategy for the transport object with a
reference to the owner's id.public P create(T transportable, W owner, DataStoreContext context)
BidirectionalDependentDao
create
in interface BidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>>
transportable
- transport object to get the data from.owner
- ownercontext
- data store contextpublic void update(P target, T source, DataStoreContext context)
BidirectionalDependentDao
update
in interface BidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>>
target
- object to updatesource
- object to take the data fromcontext
- data store contextpublic P update(Q transportable, DataStoreContext context)
BidirectionalDependentDao
update
in interface BidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>>
transportable
- transport object to get the data fromcontext
- data store contextpublic Q convert(P source)
Converter
public T convert(P source, R owner)
BidirectionalDependentDao
convert
in interface BidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>>
source
- storable object to convertowner
- the storable object's ownerpublic T convert(P storable, BaseDao<E,W,R,?,?> ownerDao, Converter<W,R> ownerConverter, DataStoreContext context)
BidirectionalDependentDao
Example when owner is a Dao
Dao<E, W, R, ?, ?> ownerDao = ...; BidirectionalDependentDao<I, P, T, ?, ?, ?, E, W, R> dependentDao = ...; DataStoreContext context = ...; P storable = ...; T transportable = dependentDao.convert(storable, ownerDao, ownerDao, context);Example when owner is a
BidirectionalDependentDao
final Dao<H, M, N, ?, ?> rootOwnerDao = ...; final BidirectionalDependentDao<E, W, R, ?, ?, ?, H, M, N> dependentOwnerDao = ...; BidirectionalDependentDao<I, P, T, ?, ?, ?, E, W, R> dependentDao = ...; final DataStoreContext context = ...; Converter<W, R> dependentOwnerConverter = new Converter<W, R>() { @Override public R convert(W source) { return dependentOwnerDao.convert(source, rootOwnerDao, rootOwnerDao, context); } }; P storable = ...; T transportable = dependentDao.convert(storable, dependentOwnerDao, dependentOwnerConverter, context);
convert
in interface BidirectionalDependentDao<I extends Serializable,P extends Storable<I> & Dependable<E>,T extends Transportable<? super T,I> & Dependent<R>,Q extends Transportable<? super Q,I> & Dependent<E>,F,S,E extends Serializable,W extends Storable<E>,R extends Transportable<? super R,E>>
storable
- storable object to convertownerDao
- owner dao to load the owner from the databaseownerConverter
- converter to use to convert the owner persistent
object to a transport objectcontext
- data store contextprotected abstract P createStorableInstance(T transportable, W owner)
transportable
- transport object to get the data from.owner
- owner.protected abstract Q doConvert(P source)
source
- persistent object to convert.source
protected abstract T doConvert(P source, R owner)
source
- persistent object to convert.owner
- owner.source
protected abstract void conformT(P target, T source)
update(Transportable, DataStoreContext)
,
thus if update(Transportable, DataStoreContext)
is overwritten
this method could have an empty implementation.target
- object to update.source
- object to take the data from.protected abstract void conformQ(P target, Q source)
update(Transportable, DataStoreContext)
,
thus if update(Transportable, DataStoreContext)
is overwritten
this method could have an empty implementation.target
- object to update.source
- object to take the data from.Copyright © 2015. All Rights Reserved.