Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » ObjectArrayMapping and ClassDescriptor(Problems with ObjectArrayMapping setup.)
ObjectArrayMapping and ClassDescriptor [message #662729] Thu, 31 March 2011 16:49 Go to next message
kardanov is currently offline kardanovFriend
Messages: 7
Registered: March 2011
Junior Member
I try to create ObjectArrayMapping using DescriptorCustomizer:
public class MyDescriptorCustomizer implements DescriptorCustomizer {
  public void customize(ClassDescriptor descriptor) throws Exception {
    // Set class descriptor to an aggregate collection.
    descriptor.descriptorIsAggregateCollection();
    // Delete old mapping (default) for my attribute:
    descriptor.removeMappingForAttributeName("attributeName");
    // Create new ObjectArrayMapping:
    ObjectArrayMapping arrayMapping = new ObjectArrayMapping(); // Set up properties.
    arrayMapping.setReferenceClass(MyClass.class);
    arrayMapping.setAttributeName("attributeName");
    arrayMapping.setFieldName("fieldName");
    arrayMapping.setStructureName("structureName");
    // Add mapping to descriptor.
    descriptor.addMapping(arrayMapping);
  }
}


Problem is the following: ObjectArrayMapping requires Class Descriptor to be an AggregateCollection, that's why I set this property for my descriptor.
But after it all other mappings (for other fields) which were of DirectToFieldMapping or AggregateObjectMapping types are lost, cause they require normal descriptor.

The exception which is thrown by Eclipse is following:
Caused by: Exception [EclipseLink-8030] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Error compiling the query [SELECT p FROM Wsensorstate p, Tkunde r WHERE r.kundeid = :kundeid AND p.id.providerid = r.providerid AND p.id.kundeid = :kundeid AND p.id.endgeraetid = :endgeraetid], line 1, column 72: unknown state or association field [id] of class [com.companyname.res.pull.api.entities.Wsensorstate]


Do you have any ideas how to avoid this problem? Or just an advice how to organize ObjectArrayMapping correctly?
Any help will be appreciated.
If you need Entity code or smth else, I can added. Thanks.
Re: ObjectArrayMapping and ClassDescriptor [message #662938 is a reply to message #662729] Fri, 01 April 2011 14:17 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1039
Registered: July 2009
Senior Member
Hello,

This seems spawned from the question at:
http://stackoverflow.com/questions/5475305/eclipselink-and-a rraymapping-jpa-problem

You should not be using descriptor.descriptorIsAggregateCollection();
on the descriptor you are trying to add the ObjectArrayMapping to. It should be on the descriptor the ObjectArrayMapping points at - the referenced object's descriptor, as it is an an object going into an Aggregate collection. Aggregates are special since they do not have their own primary keys they have to use their parents identity.

Best Regards,
Chris
Re: ObjectArrayMapping and ClassDescriptor [message #664162 is a reply to message #662938] Thu, 07 April 2011 16:59 Go to previous messageGo to next message
kardanov is currently offline kardanovFriend
Messages: 7
Registered: March 2011
Junior Member
Chris, thank you for your reply.
Probably I'm an idiot but I can't get it working. Let me describe you all the things done and probably you will show me any problem points.

I have entity:
@Entity
public class Wsensorstate implements Serializable {
    [.........]
    // Here is the problem column:
    private List<CAlarmMess> alarme;
    [.........]
}

I also have CAlarmMess class which is actually just a POJO:
public class CAlarmMess implements Serializable {
    [.........]
    private BigDecimal ereignisTypId;
    private BigDecimal ereignisKlasseId;
    private Date alarmZeit;
    private String paramWert1;
    private String paramWert2;
    private String paramWert3;
    [.........]
}

All the fields of this CAlarmMess class have corresponding fields in Oracle custom type.

I also have session customizer:
public class RPASessionCustomizer implements SessionCustomizer {
  public void customize(Session session) throws Exception {
    Server server = (Server) session;
    ObjectRelationalDataTypeDescriptor objectRelationalDataTypeDescriptor = new ObjectRelationalDataTypeDescriptor();
    objectRelationalDataTypeDescriptor.setJavaClass(CAlarmMess.class);
    objectRelationalDataTypeDescriptor.setTableName("WSENSORSTATE");
    objectRelationalDataTypeDescriptor.descriptorIsAggregate();
    objectRelationalDataTypeDescriptor.setStructureName("CAlarmMess");
    objectRelationalDataTypeDescriptor.addFieldOrdering("EreignisTypId");
    objectRelationalDataTypeDescriptor.addFieldOrdering("EreignisKlasseId");
    objectRelationalDataTypeDescriptor.addFieldOrdering("AlarmZeit");
    objectRelationalDataTypeDescriptor.addFieldOrdering("ParamWert1");
    objectRelationalDataTypeDescriptor.addFieldOrdering("ParamWert2");
    objectRelationalDataTypeDescriptor.addFieldOrdering("ParamWert3");

    objectRelationalDataTypeDescriptor.addDirectMapping("ereignisTypId", "getEreignisTypId", "setEreignisTypId", "EreignisTypId");
    objectRelationalDataTypeDescriptor.addDirectMapping("ereignisKlasseId", "getEreignisKlasseId", 	"setEreignisKlasseId", "EreignisKlasseId");
    objectRelationalDataTypeDescriptor.addDirectMapping("alarmZeit", "getAlarmZeit", "setAlarmZeit", "AlarmZeit");
    objectRelationalDataTypeDescriptor.addDirectMapping("paramWert1", "getParamWert1", 	"setParamWert1", "ParamWert1");
    objectRelationalDataTypeDescriptor.addDirectMapping("paramWert2", "getParamWert2", 	"setParamWert2", "ParamWert2");
    objectRelationalDataTypeDescriptor.addDirectMapping("paramWert3", "getParamWert3", 	"setParamWert3", "ParamWert3");

    server.addDescriptor(objectRelationalDataTypeDescriptor);

    // Creates class descriptor for object-array mapping setup.
    ClassDescriptor classDescriptor = new ClassDescriptor();

    classDescriptor.setJavaClass(CAlarmMess.class);
    classDescriptor.setTableName("WSENSORSTATE");

    classDescriptor.descriptorIsAggregateCollection();
    ObjectArrayMapping objectArrayMapping = new ObjectArrayMapping();
    objectArrayMapping.setReferenceClass(Wsensorstate.class);
    objectArrayMapping.setAttributeName("alarme");
    objectArrayMapping.setFieldName("ALARME");
    objectArrayMapping.setStructureName("CAlarmMessList");

    classDescriptor.addMapping(objectArrayMapping);
    server.addDescriptor(classDescriptor);
  }
}

This session customizer is loaded on initialization, but it gives no result. The error message is the following:
Caused by: Exception [EclipseLink-3002] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [[Ljava.lang.Object;@16f019f], of class [class [Ljava.lang.Object;], from mapping [org.eclipse.persistence.mappings.DirectToFieldMapping[alarme-->WSENSORSTATE.ALARME]] with descriptor [RelationalDescriptor(com.tsystems.res.pull.api.entities.Wsensorstate --> [DatabaseTable(WSENSORSTATE)])], could not be converted to [class [B].

So Eclipselink can see only direct-to-field mapping with relational descriptor, so the conversion can't be done.
I can remind you the DB structure.
Problem column from table SQL script:
"ALARME" "ITMSYS"."CALARMMESSLIST"

Here is CAlarmMessList type:
create or replace TYPE CAlarmMessList AS VARRAY(15) OF CAlarmMess;

And CAlarmMess type:
create or replace TYPE CAlarmMess AS OBJECT (
    EreignisTypId    NUMBER(9),
    EreignisKlasseId NUMBER(9),
    AlarmZeit        DATE,
    ParamWert1       VARCHAR2(65 CHAR),
    ParamWert2       VARCHAR2(65 CHAR),
    ParamWert3       VARCHAR2(65 CHAR),
    
    CONSTRUCTOR FUNCTION CAlarmMess RETURN SELF AS RESULT,
    CONSTRUCTOR FUNCTION CAlarmMess(iEreignisTypId    IN NUMBER, iEreignisKlasseId IN NUMBER, iAlarmZeit IN DATE) RETURN SELF AS RESULT,
    CONSTRUCTOR FUNCTION CAlarmMess(iEreignisTypId    IN NUMBER, iEreignisKlasseId IN NUMBER, iAlarmZeit IN DATE, iParamWert1IN VARCHAR2) RETURN SELF AS RESULT,
    CONSTRUCTOR FUNCTION CAlarmMess(iEreignisTypId    IN NUMBER, iEreignisKlasseId IN NUMBER, iAlarmZeit IN DATE, iParamWert1 IN VARCHAR2, iParamWert2 IN VARCHAR2) 	RETURN SELF AS RESULT
);


Do you see any problems here? What should I change?
I will greatly appreciate any help and further advices.

[Updated on: Thu, 07 April 2011 17:00]

Report message to a moderator

Re: ObjectArrayMapping and ClassDescriptor [message #664175 is a reply to message #664162] Thu, 07 April 2011 17:52 Go to previous messageGo to next message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

The problem is you are adding two descriptors for the same class,

Instead of creating the 2nd descriptor, you need to lookup the existing object and add the mapping,

// Creates class descriptor for object-array mapping setup.
ClassDescriptor classDescriptor = session.getDescriptor(Wsensorstate.class);

classDescriptor.removeMappingForAttributeName("alarme");

ObjectArrayMapping objectArrayMapping = new ObjectArrayMapping();
objectArrayMapping.setReferenceClass(CAlarmMess.class);
objectArrayMapping.setAttributeName("alarme");
objectArrayMapping.setFieldName("ALARME");
objectArrayMapping.setStructureName("CAlarmMessList");

classDescriptor.addMapping(objectArrayMapping);




James : Wiki : Book : Blog : Twitter
Re: ObjectArrayMapping and ClassDescriptor [message #664181 is a reply to message #664175] Thu, 07 April 2011 18:14 Go to previous messageGo to next message
kardanov is currently offline kardanovFriend
Messages: 7
Registered: March 2011
Junior Member
Thank you for the reply, James.
Don't you think that there will be problem related with the type of descriptor? Cause ObjectArrayMapping requires Aggregate Collection descriptor, but the one returned by session.getDescriptor(Wsensorstate.class) method will be Relational Descriptor?
It seems to be the problem described in my first message.
Re: ObjectArrayMapping and ClassDescriptor [message #664657 is a reply to message #664181] Mon, 11 April 2011 14:29 Go to previous messageGo to next message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

What error do you currently get, and what is your customizer?

The descriptor for CAlarmMess must be a ObjectRelationalDataTypeDescriptor and be aggregate as it is mapped to a Struct, you had this correct.

The descriptor for Wsensorstate is mapped to a table, so should be a normal Entity descriptor. I think this is a bug (please log the bug) that currently requires the source descriptor to also be a ObjectRelationalDataTypeDescriptor, so you may need to add a descriptor for Wsensorstate as a ObjectRelationalDataTypeDescriptor, and add all of its mappings. It must not be aggregate though, as it is mapped to a table.

In general array types in the database are not very common. You may consider using a standard SQL relationship instead, by just have another table and a OneToManny relationship.


James : Wiki : Book : Blog : Twitter
Re: ObjectArrayMapping and ClassDescriptor [message #665359 is a reply to message #664657] Thu, 14 April 2011 12:40 Go to previous messageGo to next message
kardanov is currently offline kardanovFriend
Messages: 7
Registered: March 2011
Junior Member
Thanks for your reply, James.
Currently i have customizer and get error as described in my message on April, 7th.
If I change customizer in the way you suggested:
public class RPASessionCustomizer implements SessionCustomizer {
  public void customize(Session session) throws Exception {
    Server server = (Server) session;
    ObjectRelationalDataTypeDescriptor objectRelationalDataTypeDescriptor = new ObjectRelationalDataTypeDescriptor();
    objectRelationalDataTypeDescriptor.setJavaClass(CAlarmMess.class);
    objectRelationalDataTypeDescriptor.setTableName("WSENSORSTATE");
    objectRelationalDataTypeDescriptor.descriptorIsAggregate();
    objectRelationalDataTypeDescriptor.setStructureName("CAlarmMess");
    objectRelationalDataTypeDescriptor.addFieldOrdering("EreignisTypId");
    objectRelationalDataTypeDescriptor.addFieldOrdering("EreignisKlasseId");
    objectRelationalDataTypeDescriptor.addFieldOrdering("AlarmZeit");
    objectRelationalDataTypeDescriptor.addFieldOrdering("ParamWert1");
    objectRelationalDataTypeDescriptor.addFieldOrdering("ParamWert2");
    objectRelationalDataTypeDescriptor.addFieldOrdering("ParamWert3");

    objectRelationalDataTypeDescriptor.addDirectMapping("ereignisTypId", "getEreignisTypId", "setEreignisTypId", "EreignisTypId");
    objectRelationalDataTypeDescriptor.addDirectMapping("ereignisKlasseId", "getEreignisKlasseId", 	"setEreignisKlasseId", "EreignisKlasseId");
    objectRelationalDataTypeDescriptor.addDirectMapping("alarmZeit", "getAlarmZeit", "setAlarmZeit", "AlarmZeit");
    objectRelationalDataTypeDescriptor.addDirectMapping("paramWert1", "getParamWert1", 	"setParamWert1", "ParamWert1");
    objectRelationalDataTypeDescriptor.addDirectMapping("paramWert2", "getParamWert2", 	"setParamWert2", "ParamWert2");
    objectRelationalDataTypeDescriptor.addDirectMapping("paramWert3", "getParamWert3", 	"setParamWert3", "ParamWert3");

    server.addDescriptor(objectRelationalDataTypeDescriptor);

    ClassDescriptor classDescriptor = session.getDescriptor(Wsensorstate.class);
    classDescriptor.removeMappingForAttributeName("alarme");
    ObjectArrayMapping objectArrayMapping = new ObjectArrayMapping();
    objectArrayMapping.setReferenceClass(CAlarmMess.class);
    objectArrayMapping.setAttributeName("alarme");
    objectArrayMapping.setFieldName("ALARME");
    objectArrayMapping.setStructureName("CAlarmMessList");
    classDescriptor.addMapping(objectArrayMapping);
  }
}

It gives me following error:
Exception [EclipseLink-197] (Eclipse Persistence Services - 2.1.2.v20101206-r8635): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: The mapping [alarme] is not the appropriate type for this descriptor
Mapping: org.eclipse.persistence.mappings.structures.ObjectArrayMapping[alarme]
Descriptor: RelationalDescriptor(com.companyname.api.entities.Wsensorstate --> [DatabaseTable(WSENSORSTATE)])

So the descriptor is relational descriptor, but I try to add aggregate mapping.

Any ideas?
Re: ObjectArrayMapping and ClassDescriptor [message #665417 is a reply to message #665359] Thu, 14 April 2011 14:59 Go to previous message
James Sutherland is currently offline James SutherlandFriend
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

You need to make the descriptor for Wsensorstate a ObjectRelationalDataTypeDescriptor as well.

You should be able to create a new one, define its primary key, table and mappings and register it with the session to override the JPA generated one. You could probably copy these over from the existing descriptor.



James : Wiki : Book : Blog : Twitter
Previous Topic:Create more than one EntityManagerFactory for the same PersistenceUnit
Next Topic:JPA2.1
Goto Forum:
  


Current Time: Sun Nov 23 00:50:53 GMT 2014

Powered by FUDForum. Page generated in 0.02464 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software