Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-dev] Question aboutEmbeddedAccessor#processEmbeddableClass()

Hi Mark,

So I wouldn't use the word store, but rather a new EmbeddableAccessor should be created and processed for each usage of an Embedded. Internally (beyond the metadata processing objects) EclipseLink uses/has only one class descriptor to every class (entity or embeddable) of the persistence unit.

I took a look at your prefix annotation. I would think you could achieve this functionality by adding another processing method to EmbeddedAccessor to iterate over the mappings of the embeddable class (once it has been processed) and add a field name translation (just like we do for attribute overrides) using the prefix to each field of the mappings of the embeddable? If there is a nested case, you would bury down into its mappings and apply the prefix, unless the nested embedded defined its own prefix, and so on.

So I'm not sure if in your case you need to worry about the notion of the owning descriptor? The notion of the owning descriptor was introduced post JPA 1.0 to facilitate embeddables (nested or not) to specify metadata beyond what was allowed in the spec. Namely things like Id's, GeneratedValue's etc .. those items which required metadata settings on to the owning entity. Unfortunately in the current design those metadata items are only processed for the first entity that uses the shared embedded (this is a bug, which I pointed out earlier).

The model you outlined below should work no problem (it doesn't have owning descriptor dependencies)

I hope this helps!

Cheers,
Guy

----- Original Message ----- From: "Mark Struberg" <struberg@xxxxxxxx> To: <eclipselink-dev@xxxxxxxxxxx>; "Guy Pelletier" <guy.pelletier@xxxxxxxxxx>
Sent: Wednesday, November 12, 2008 12:29 PM
Subject: Re: [eclipselink-dev] Question aboutEmbeddedAccessor#processEmbeddableClass()


Hi Guy!

Txs 4 the quick response!

So (I better repeat this to make sure I understood it correctly) the question is: should we store the aggregated EmbeddableAccessor once for each table, or once for every usage of @Embedded, correct?

As you've maybe read, I'm currently working on a prefix annotation for embedded classes. If this will be part of @Embedded or an own annotation doesn't imho change much, in any case we have add the m_prefix handling to the EmbeddedAccessor. So, I'm sure there is another way in the chain to add the prefix to the column names, but my gut feeling tells me that this would be much easier to implement if there is an EmbeddableAccessor for every Embedding. Including nested embeddings.

Btw, what about nested embeddings currently?
I did not debug through, but can you imagine a situation where we do also need the info parted in this case?

An example:

@Embeddable
public class Price {
private BigDecimal amount;
private String     currency;
}

@Embeddable
public class ListedPrice {
private int someValue;

@Embedded
@SomeFancyPriceModification
private Price lPrice;
}

@Entity
public class Purchase {
@Id @GeneratedValue private int id;

@Embedded
private ListedPrice listedPrice;

@Embedded
@AnotherFancyPriceModification
private Price soldPrice;
}

1.) Are there any valid annotations which may affect the fields? I know about the AttributeOverrides which has a special handling in EmbeddedAccessor, so this should not be a problem for @Embedding. But what happens if AttributeOverrides is being used inside a nested class (ListedPrice)? 2.) If so, may this be handled if we only have one EmbeddableAccessor per OwningDescriptor?

Humm, my brain is smoking, hope this post isn't getting too confusing ;)


LieGrue,
strub

P.S.:
And a few additional thoughts coming to my mind:
a) What would be the downside of storing the EmbeddableAccesor for each @Embedded usage? We have to store one for each entity anyway. Technically his would imho only have an effect if there are many embeddings of the same type in the same table. Logically it is simply a difference if an Accessor represents a 'database archetype' or a specific usage of this archetype. b) Could we split the EmbeddedAccessor in a 'static' part and a part for each embedding? c) What about adding back-references to the actual EmbeddedAccessor for each processing step and stay with 1 EmbeddableAccessor (which then has to lookup varying parts from it's embedding)?


--- Guy Pelletier <guy.pelletier@xxxxxxxxxx> schrieb am Mi, 12.11.2008:

Von: Guy Pelletier <guy.pelletier@xxxxxxxxxx>
Betreff: Re: [eclipselink-dev] Question aboutEmbeddedAccessor#processEmbeddableClass()
An: eclipselink-dev@xxxxxxxxxxx
Datum: Mittwoch, 12. November 2008, 16:05
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_______________________________________________
eclipselink-dev mailing list
eclipselink-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-dev






Back to the top