[ 
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

Reply via email to