Domanda

I am using EclipseLink 2.4.0 and I am trying to find a way to generate the following DDL statements:

ALTER TABLE DELTA ADD CONSTRAINT DELTAFK1 FOREIGN KEY (APPKEY, NEWREVISION) REFERENCES REVISION (APPKEY, REVISION);
ALTER TABLE DELTA ADD CONSTRAINT DELTAFK2 FOREIGN KEY (APPKEY, OLDREVISION) REFERENCES REVISION (APPKEY, REVISION);

Each row in the DELTA table represents the changes between the two specified revisions and the primary key is made up of APPKEY, NEWREVISION, and OLDREVISION. Only the first alter statement is being generated with the following relationship annotations defined in the Delta.java class:

public class Delta {

@EmbeddedId
private DeltaPK deltaPk;

@ManyToOne
@PrimaryKeyJoinColumns({
       @PrimaryKeyJoinColumn(name="appKey", referencedColumnName="appKey"),
       @PrimaryKeyJoinColumn(name="newRevision", referencedColumnName="revision")
})
private Revision newRevision;

@ManyToOne
@PrimaryKeyJoinColumns({
       @PrimaryKeyJoinColumn(name="appKey", referencedColumnName="appKey"),
       @PrimaryKeyJoinColumn(name="oldRevision", referencedColumnName="revision")
})
private Revision oldRevision;

The name values of each PrimaryKeyJoinColumn, ‘appKey’, ‘oldRevision’, and ‘newRevision’ are all fields defined in the DeltaPK class and the referencedColumnName values are fields defined in the Revision class.

I’ve tried a bunch of variations, and the closest I’ve gotten was when I comment out the PrimaryKeyJoinColumn for ‘appKey’ for the oldRevision object. Then the second alter statement is generated, but it only includes the oldRevision value (not appKey), as you would expect. Any thoughts or suggestions on how to accomplish this would be appreciated.

È stato utile?

Soluzione

I had to walk through the EclipseLink source code in the debugger for a while before I found out how to solve this one. It turns out there was one key part of the problem that I did not mention in my original question (because I didn't know it was part of the problem). The fields 'appKey' and 'revision' from the Revision class are not the primary key for that table, however, they do make up a uniqueness constraint:

@Table(
    name = "REVISION",
    uniqueConstraints = @UniqueConstraint(columnNames = {"appKey", "revision"})
)

It turns out that EclipseLink was generating the name of the foreign key constraint partially based on the ordering of the columnNames in this uniqueness constraint. This caused both of my foreign key constraints to be generated with the same name which ultimately led to the second one being ignored and not generated. (See the following methods in org.eclipse.persistence.tools.schemaframework.TableDefinition if you'd like to put together all the details.)

buildForeignKeyConstraint(List<String> fkFieldNames, List<String> pkFieldNames, TableDefinition targetTable, DatabasePlatform platform)
buildForeignKeyConstraintName(String tableName, String fieldName, int maximumNameLength, DatabasePlatform platform)
addForeignKeyConstraint(ForeignKeyConstraint foreignKey)

In short, when I simply reordered the values for cloumnNames like so:

@UniqueConstraint(columnNames = {"revision", "appKey"})

I got two differently named foreign key constraints (because of the two mappings between 'revision' and 'newRevison' and 'oldRevision') as shown below:

ALTER TABLE DELTA ADD CONSTRAINT DELTA_NEWREVISION FOREIGN KEY (NEWREVISION, APPKEY) REFERENCES REVISION (REVISION, APPKEY)
ALTER TABLE DELTA ADD CONSTRAINT DELTA_OLDREVISION FOREIGN KEY (OLDREVISION, APPKEY) REFERENCES REVISION (REVISION, APPKEY)

You may get slightly different output for different database platforms (I was using Derby), but I think the general issue and solution are the same. I hope I explained that clear enough to help someone else out in the future.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top