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,

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

Back to the top