Hello,
The OneToOne mapping should be the mapping within the primaryKeyMappings in this case, as that is the only attribute that can be trusted to have the correct value in it as it is the only writable mapping.
Support for non-writable PK's could be added but I think it would be limited in value as it would prevent creation of entities as a side effect.
--Gordon
-----Original Message-----
From: Wonseok Kim [mailto:guruwons_at_gmail.com]
Sent: Tuesday, August 08, 2006 3:32 AM
To: persistence_at_glassfish.dev.java.net
Subject: Re: part of an embedded object is read-only...
When I see the code AggregateObjectMapping's readOnly flag is always set false so isReadOnly() seems to be meaningless.
I think it needs to check each field of AggregateObjectMapping for read-only. Following can be one solution.
public void initialize(AbstractSession session) throws DescriptorException {
...
// Add field to mapping association
for (Enumeration fields = mapping.getFields().elements(); fields.hasMoreElements();) {
// Object field = fields.nextElement();
DatabaseField field = (DatabaseField) fields.nextElement();//field is always DatabaseField
if (!mapping.isReadOnly() && !field.isReadOnly()) {//PATCH: if AggregateObjectMapping check if each field is read-only
if (getMappingsByField().containsKey(field)) {
// We cannot determine if aggregate mapping for the field are read-only, so ignore exception.
if (!mapping.isAggregateObjectMapping()) {
session.getIntegrityChecker().handleError(DescriptorException.multipleWriteMappingsForField(field.toString(), mapping));
}
...
But this causes another problem in initializePrimaryKey() for Embedded object which has read-only primary key like Sahoo's sample.
@Entity
public class Table1 implements java.io.Serializable {
@EmbeddedId
protected Table1PK table1PK;
@JoinColumn(name = "ID", referencedColumnName = "ID")
@OneToOne
private Table2 table2;
...
@Embeddable
public class Table1PK implements java.io.Serializable {
@Column(name = "ID", nullable = false, insertable=false, updatable=false)
private int id;
...
In initializePrimaryKey() it find and set primaryKeyMappings from mappingsByField map which contains non-read-only mappings. So if embedded object has read-only primary key, its AggregateObjectMapping can not be found and put into primaryKeyMappings.
Instead another mapping OneToOneMapping is found and put into primaryKeyMappings incorrectly(so cause problem later).
Basically I wonder that TopLink can handle read-only primary key mapping properly, because when I have following mapping in another sample:
@Id
@Column(name="ID", insertable = false, updatable = false)
public int id;
it throws following exception:
Exception Description: There should be one non-read-only mapping defined for the primary key field [ TABLE1.ID].
Descriptor: RelationalDescriptor(Table1 --> [DatabaseTable(TABLE1)])
So IMHO to fix the issue we need to be clear about read-only primary key first.
-Wonseok
On 8/7/06, Sanjeeb Kumar Sahoo <Sanjeeb.Sahoo_at_sun.com> wrote:
(Resending as the earlier email which had a wrong subject.)
Hi Tom, Gordon,
I am looking into issue
https://glassfish.dev.java.net/issues/show_bug.cgi?id=894 . Looking at
the code I see that the metadata processing code is correctly processing
the insertable and updatable values that are specified in the Embeddable
class. An *AggregateObjectMapping* type of mapping is also created for
the embedded field. The bug seem to be in ObjectBuilder.java which is
reporting an incorrect exception. See code below from ObjectBuilder.java:
public void initialize(AbstractSession session) throws
DescriptorException {
...
if (!mapping.isReadOnly()) {
if (getMappingsByField().containsKey(field)) {
// We cannot determine if aggregate mapping for
the field are read-only, so ignore exception.
if (!mapping.isAggregateObjectMapping()) {
session.getIntegrityChecker().handleError(DescriptorException.multipleWriteMappingsForField(field.toString(),
mapping));
}
}
...
As you can see, from the above code, it is checking if the
AggregateObjectMapping is readonly or not. Should it not instead check
individual mapping objects that are part of the AggregateObjectMapping?
What I don't understand is why is their a boolean type field called
*isReadOnly* on an AggregateObjectMapping. What is the semantics of that
boolean flag? /Does TopLink Essential not support a part of an embedded
object to be read-only?/
Thanks,
Sahoo
--
Wonseok Kim
Senior Developer, TmaxSoft