You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by "Vermeulen (JIRA)" <ji...@apache.org> on 2013/04/24 13:13:15 UTC
[jira] [Commented] (OPENJPA-2375) generate predictable names for
primary and foreign keys
[ 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