Hi Mark,
Happy to hear you're enjoying
working with the code.
What you have pointed out is indeed a problem and
is problamatic for a number of use cases. See the following bug
(https://bugs.eclipse.org/bugs/show_bug.cgi?id=250144)
The notion of the
owning descriptor should remain however (e.g. an id field defined on an
embeddable requires setting metadata on the actual owning entity) , but the
problem as you have pointed out is that the embeddable class is only processed
once from the first entity that references it. So this is incorrect. The
embeddable class should likely be cloned (similarly as we do with mapped
superclasses) and re-processed using the context or each owning descriptor.
Note, the whole class likely will not need to be re-processed, likely only the
accessors and again you'll have to be careful as to which accessors gets
re-processed since you don't want all the metadata from your embeddable class
stored on the owning descriptor.
See the reloadMappedSuperclass
method from ORMetadata. Notice, it clones a mapped superclass by reloading
it from XML. In your case you would have to handle the case where the Embeddable
was not loaded from XML (the accessible object will not have an associated
entity mappings object) and you'd likely just have to create a new instance
of the EmbeddableAccessor. I've just recently built a similar method for
Entities (in my current work for TABLE_PER_CLASS support, see
below)
/** * INTERNAL: * This
method should be called to reload an entity (that was either * loaded
from XML or an annotation) as a way of cloning it. This is needed *
when we process TABLE_PER_CLASS inheritance. We must process the
parent * classes for every subclasses descriptor. The processing is
similar to * that of processing a mapped superclass, in that we process
the parents * with the subclasses context (that is, the descriptor we
are given). */ protected EntityAccessor reloadEntity(EntityAccessor
entity, MetadataDescriptor descriptor) { if
(m_accessibleObject.getEntityMappings() == null) {
// Create a new EntityAccesor.
EntityAccessor entityAccessor = new
EntityAccessor(entity.getAnnotation(), entity.getJavaClass(),
entity.getProject()); // Things we care
about ...
entityAccessor.setDescriptor(descriptor);
entityAccessor.getDescriptor().setDefaultAccess(entity.getDescriptor().getDefaultAccess());
return entityAccessor; } else
{ return
m_accessibleObject.getEntityMappings().reloadEntity(entity,
descriptor); } }
Hope this helps!
Cheers,
Guy
----- Original Message ----- From: "Mark Struberg"
<struberg@xxxxxxxx> To: <eclipselink-dev@xxxxxxxxxxx> Sent:
Wednesday, November 12, 2008 6:04 AM Subject: [eclipselink-dev] Question
aboutEmbeddedAccessor#processEmbeddableClass()
Hi!
I've read
through the eclipselink sources and like to add a few
features.
Generally, I'd to say that it is a really well done and _very_
readable source! I did look at the sources for only 2 evenings now (and I really
enjoyed digging into it), so don't be rude if I completely misinterpreted/not
understood something yet :)
There's a point in the EmbeddedAccesor which
I do not understand:
In the function processEmbeddableClass(), a 'cached'
EmbeddedAccessor instance is retrieved (line #
299) EmbeddableAccessor accessor =
getProject().getEmbeddableAccessor(getReferenceClassName());
So I'll get
the same EmbeddableAccessor instance for EVERY embedding of the same
class.
A bit later in the source (line # 349), this EmbeddableAccessor
will be filled with the
OwningDescriptor:
accessor.setOwningDescriptor(getOwningDescriptor());
BUT: imho the owning
descriptor may be different for each @Embedded !?
In praxis this means,
that the EmbeddableAccessor always points to the Table-Descriptor of the 'first'
occurence (which one this ever may be -> random generator?), and the other
ones may simply contain wrong values.
My
example:
@Embeddable public class Price { private BigDecimal
amount; private String
currency; }
@Entity public class Purchase
{ @Id @GeneratedValue private int id;
@Embedded(prefix =
"N_") private Price netPrice;
@Embedded(prefix = "G_") private
Price grossPrice; }
@Entity public class OtherUseOfPrice
{ @Id @GeneratedValue private int id;
@Embedded(prefix =
"O_") private Price otherPrice; }
In the debugger I got the
following memory addresses:
O_ id=40 accessor=98 getowningDescriptor()=
45 N_ id=101 accessor=98 getowningDescriptor()= 102 G_ id=116 accessor=98
getowningDescriptor()= 102
And as expected, the accessor of the
embeddings of netPrice (N_) and grossPrice (G_) point to the wrong
m_owningDescriptor 45 instead of the correct 102
Does this have any
impact on the result? If not, we also could remove the owningDescriptor from the
EmbeddableAccessor, otherwise it may be a source of problems,
isn't?
_______________________________________________ eclipselink-dev mailing
list eclipselink-dev@xxxxxxxxxxx https://dev.eclipse.org/mailman/listinfo/eclipselink-dev
|