Hi,
I am using the EclipseLink API to create dynamic entities to represent a graph stored in database tables. The links are stored in their own table, which contains a link ID column, the start node ID and the end node ID columns, plus other user-defined columns. The nodes have their own table, where a node ID is stored plus other user-defined columns.
When doing the mapping from the links table to the nodes table I am doing this with the API:
OneToOneMapping startNodeMapping = dynamicLinkTypeBuilder.addOneToOneMapping("startNode", dynamicNodeTypeBuilder.getType(), "NODE_ID");
OneToOneMapping endNodeMapping = dynamicLinkTypeBuilder.addOneToOneMapping("endNode", dynamicNodeTypeBuilder.getType(), "NODE_ID");
When running the previous code I receive the following message in the stack trace:
Local Exception Stack: Exception [EclipseLink-48] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [TEST_NETWORK_LINK.NODE_ID]. Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.OneToOneMapping[startNodeId]
This exception is thrown because I am mapping two fields (startNode and endNode) from the same entity to the same column/field in a different table/entity.
Do you know what could I do in order to solve this mapping problem? Would you suggest a different strategy? I cannot change the tables structure and I don’t want to make one of the mappings “read only”, but I am free to change the dynamic mappings.
Thank you!
The problem is as the error message states – you are using the “NODE_ID” field as a foreign key in both the startNode and endNode mappings. Essentially your object’s startNode will always == the endNode when read back from the database. I believe you will want to specify different fields for the two mappings if they are meant to reference different nodes, so that they use their own foreign key. eg:
OneToOneMapping startNodeMapping = dynamicLinkTypeBuilder.addOneToOneMapping(“startNode”, dynamicNodeTypeBuilder.getType(), “START_NODE_ID”);
OneToOneMapping endNodeMapping = dynamicLinkTypeBuilder.addOneToOneMapping(“endNode”, dynamicNodeTypeBuilder.getType(), “END_NODE_ID”);
Both will automatically reference the primary key in the referenced table, which I assume is “NODE_ID”.