It turned out the whole problem was not being able to find "version".
I still don't understand why I didn't see that exception in the
console, and I am quite sure it wasn't there (even with all log levels
set to Trace). After failing to find it, OpenJPA didn't create any
tables (including OPENJPA_SEQUENCE_TABLE), and OPENJPA_SEQUENCE_TABLE
simply happened to be the first table it queried in my test.
Stripping delimiters later was done for two reasons: 1) better looking
generated SQL; 2) going back to @UniqueConstraint(columnNames = {
"name", "version" })).
What's the reasoning for DBIdentifierUtilImpl.makeIdentifierValid
uppercasing all non-delimited identifiers, by the way?
On Wed, Jun 13, 2012 at 11:26 PM, Kevin Sutter [via OpenJPA]
<[email protected]> wrote:
> Thanks, Alexey, for your debugging efforts. This seems to indicate an
> issue with our delimited identifier support. One clarification, when you
> said that changing the UniqueConstraint fixed the problem, did you mean
> just the JUnit exception that you posted about not able to find "version",
> or did it fix both of your issues?
>
> @UniqueConstraint(columnNames = { "name", "\"version\"" }))
>
> I'm assuming it only resolved the JUnit exception since you still had to
> hack another solution with stripping the delimiters...
>
> Thanks,
> Kevin
>
> On Wed, Jun 13, 2012 at 3:00 AM, Alexey Romanov
> <[hidden email]>wrote:
>
>> So the problem is that if I don't delimit column names,
>> DBIdentifierUtilImpl.makeIdentifierValid (called from
>> dict.getValidColumnName) will convert them to upper case, whether I want
>> it
>> or not. The ugly solution I came up with is to delimit them and strip the
>> delimiters later. Unfortunately, this leads to code duplication :( This is
>> what I have at the moment:
>>
>>
>> package ru.focusmedia.odp.server.datastore.jpa.impl;
>>
>> import org.apache.openjpa.jdbc.identifier.DBIdentifier;
>> import org.apache.openjpa.jdbc.identifier.Normalizer;
>> import org.apache.openjpa.jdbc.meta.FieldMapping;
>> import org.apache.openjpa.jdbc.meta.ValueMapping;
>> import org.apache.openjpa.jdbc.schema.Column;
>> import org.apache.openjpa.jdbc.schema.Table;
>> import org.apache.openjpa.meta.JavaTypes;
>> import org.apache.openjpa.persistence.jdbc.PersistenceMappingDefaults;
>>
>> public class ImprovedMappingDefaults extends PersistenceMappingDefaults {
>> @Override
>> protected void correctName(Table table, Column col) {
>> String originalName = col.getIdentifier().getName();
>> boolean wasOriginallyDelimited =
>> Normalizer.isDelimited(originalName);
>> DBIdentifier name = DBIdentifier.newColumn(originalName,
>> !wasOriginallyDelimited);
>> DBIdentifier validName = dict.getValidColumnName(name,
>> table);
>> validName = addUnderscores(validName,
>> wasOriginallyDelimited);
>> col.setIdentifier(validName);
>> table.addCorrectedColumnName(validName, true);
>> }
>>
>> @Override
>> public void populateJoinColumn(FieldMapping fm, Table local, Table
>> foreign,
>> Column col, Object target, int pos, int cols) {
>> if (!(target instanceof Column))
>> return;
>>
>> // if this is a bidi relation, prefix with inverse field
>> name, else
>> // prefix with owning entity name
>> FieldMapping[] inverses = fm.getInverseMappings();
>> DBIdentifier sName = DBIdentifier.NULL;
>> String originalName = inverses.length > 0 ?
>> inverses[0].getName() : fm
>> .getDefiningMapping().getTypeAlias();
>> boolean wasOriginallyDelimited =
>> Normalizer.isDelimited(originalName);
>> sName = DBIdentifier.newColumn(originalName,
>> !wasOriginallyDelimited);
>> DBIdentifier targetName = ((Column)
>> target).getIdentifier();
>> DBIdentifier tempName = DBIdentifier.NULL;
>> if ((sName.length() + targetName.length()) >=
>> dict.maxColumnNameLength) {
>> tempName = DBIdentifier.truncate(sName,
>> dict.maxColumnNameLength
>> - targetName.length() - 1);
>> }
>> // suffix with '_' + target column
>> if (DBIdentifier.isNull(tempName))
>> tempName = sName;
>> sName = DBIdentifier.combine(tempName,
>> targetName.getName());
>> sName = dict.getValidColumnName(sName, foreign);
>> sName = addUnderscores(sName, wasOriginallyDelimited);
>> col.setIdentifier(sName);
>> }
>>
>> @Override
>> public void populateForeignKeyColumn(ValueMapping vm, DBIdentifier
>> sName,
>> Table local, Table foreign, Column col, Object target, boolean
>> inverse,
>> int pos, int cols) {
>> boolean elem = vm == vm.getFieldMapping().getElement()
>> && vm.getFieldMapping().getTypeCode() != JavaTypes.MAP;
>>
>> // if this is a non-inverse collection element key, it must be
>> in
>> // a join table: if we're not prepending the field name, leave
>> the
>> // default
>> if (!getPrependFieldNameToJoinTableInverseJoinColumns() &&
>> !inverse && elem)
>> return;
>>
>> // otherwise jpa always uses <field>_<pkcol> for column name,
>> even
>> // when only one col
>> if (target instanceof Column) {
>> if (DBIdentifier.isNull(sName)) {
>> sName = col.getIdentifier();
>> } else {
>> String originalName = elem ?
>> vm.getFieldMapping().getName() :
>> Normalizer.removeHungarianNotation(sName.getName());
>> boolean wasOriginallyDelimited =
>> Normalizer.isDelimited(originalName);
>> sName = DBIdentifier.newColumn(originalName,
>> !wasOriginallyDelimited);
>> sName = DBIdentifier.combine(sName,
>> ((Column)target).getIdentifier().getName());
>>
>> // No need to check for uniqueness.
>> sName = dict.getValidColumnName(sName, local, false);
>> sName = addUnderscores(sName,
>> wasOriginallyDelimited);
>> }
>> col.setIdentifier(sName);
>> }
>> }
>>
>> private DBIdentifier addUnderscores(DBIdentifier sName,
>> boolean wasOriginallyDelimited) {
>> String nameWithUnderscores =
>> addUnderscores(sName.getName());
>> if (!wasOriginallyDelimited) {
>> nameWithUnderscores = Normalizer
>>
>> .removeDelimiters(nameWithUnderscores);
>> }
>> sName = DBIdentifier.newColumn(nameWithUnderscores, false);
>> return sName;
>> }
>>
>> // taken from Hibernate's ImprovedNamingStrategy
>> private static String addUnderscores(String name) {
>> StringBuilder buf = new StringBuilder(name.replace('.',
>> '_'));
>> for (int i = 1; i < buf.length() - 1; i++) {
>> if (Character.isLowerCase(buf.charAt(i - 1))
>> &&
>> Character.isUpperCase(buf.charAt(i))
>> &&
>> Character.isLowerCase(buf.charAt(i + 1))) {
>> buf.insert(i++, '_');
>> }
>> }
>> return buf.toString().toLowerCase();
>> }
>> }
>>
>>
>> --
>> View this message in context:
>>
>> http://openjpa.208410.n2.nabble.com/Change-of-MappingDefaults-breaks-OPENJPA-SEQUENCE-TABLE-tp7580246p7580270.html
>> Sent from the OpenJPA Users mailing list archive at Nabble.com.
>>
>
>
> ________________________________
> If you reply to this email, your message will be added to the discussion
> below:
> http://openjpa.208410.n2.nabble.com/Change-of-MappingDefaults-breaks-OPENJPA-SEQUENCE-TABLE-tp7580246p7580279.html
> To unsubscribe from Change of MappingDefaults breaks OPENJPA_SEQUENCE_TABLE,
> click here.
> NAML
--
View this message in context:
http://openjpa.208410.n2.nabble.com/Change-of-MappingDefaults-breaks-OPENJPA-SEQUENCE-TABLE-tp7580246p7580281.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.