[
https://issues.apache.org/jira/browse/OPENJPA-2375?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13640343#comment-13640343
]
Vermeulen commented on OPENJPA-2375:
------------------------------------
Here's what I already tried:
The most obvious way to implement this is by using the
openjpa.jdbc.MappingDefaults property to set a custom MappingDefaults strategy.
So I extended PersistenceMappingDefaults and have overridden
getForeignKey(ValueMapping, DBIdentifier, Table, Table, boolean)
getJoinForeignKey to set the foreign key identifier to
DBIdentifier.preCombine(DBIdentifier.combine(table.getIdentifier(),
refersTo.getName()), "FK")
This actually works nicely. However the method
getPrimaryKeyIdentifier(ClassMapping, Table) is never called. It does seem to
be called when using the option DefaultMissingInfo=false. However I get an
exception where it cannot handle a @MappedSuperclass that has a generated
primary key column:
org.apache.openjpa.util.MetaDataException: For
"nl.hm.olga.core.entity.AbstractEntity.id", expected 1 column(s), but found 0.
So I am using DefaultMissingInfo = true.
After inspecting OpenJPA's code I found a workaround hack. The PK is created in
OpenJPA class FullClassStrategy. Somehow the boolean adapt is set to false with
DefaultMissingInfo = true. I extended this class and copy/pasted the code of
the map method and always enabled the line that gets the PK identifier:
pkname =
cls.getMappingRepository().getMappingDefaults()
.getPrimaryKeyIdentifier(cls, table);
This custom extended class can be used by setting this configuration in
persistence.xml:
<property name="openjpa.jdbc.MappingDefaults"
value="nl.hm.olga.core.dao.openjpa.KeyConstraintNamesMappingDefaults(ForeignKeyDeleteAction=restrict,
JoinForeignKeyDeleteAction=restrict,
BaseClassStrategy=org.apache.openjpa.jdbc.meta.strats.PrimaryKeyConstraintNameFullClassStrategy)"
/>
However this introduces a bug: I am using inheritance with
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) and this strategy is
overwritten by the base class strategy resulting in tables for the abstract
superclass that otherwise wouldn't exist. It also doesn't work as the
SubclassStrategy for openjpa.jdbc.MappingDefaults
I found out the hard way that BaseClassStrategy and SubclassStrategy are null
by default. This is not clear from the documentation; it even states that flat
is the default strategy which I verified to be false: an appropriate strategy
is selected based on configuration on the entities. Using these settings will
ignore the individual settings in the entities and use the strategies for all
entities.
(This feels similar to when the Java switch statement would always execute the
default case if it is present....)
Lesson learned: don't mess with OpenJPA internals and be very careful with
custom plugin strategies.
Even though I got it mostly working I'm giving up because it's so dangerous.
Will look into a SQL only way.
> generate predictable names for primary and foreign keys
> -------------------------------------------------------
>
> Key: OPENJPA-2375
> URL: https://issues.apache.org/jira/browse/OPENJPA-2375
> Project: OpenJPA
> Issue Type: Improvement
> Components: jdbc
> Affects Versions: 2.2.1
> Reporter: Vermeulen
>
> When the MappingTool creates the database schema, OpenJPA will let the
> database determine the names of primary and foreign key constraints.
> Microsoft SQL server uses a seemingly random number which changes each time
> the database schema is generated. This makes it harder to create SQL scripts
> that refer to these keys or use schema comparison tools.
> Names of generated keys could e.g. be:
> PK_<table name>
> FK_<table name>_<referenced foreign column name>
> (Perhaps adding foreign table name as well to prevent possible name clashes)
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira