Alexy - I've been asked to look into this. I don't have a lot of time now to dig into it. But, a quick look makes me wonder if you could fix this by using the DBDictionary property "schemaCase". The default value is "upper". I think you want to use "preserve". I see you've used a dictionary property, so you should be able to figure this out. If that doesn't work, I'll look into this further tomorrow.
Dianne On Wed, Jun 13, 2012 at 3:09 PM, Alexey Romanov <[email protected]>wrote: > 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. > -- Thanks - Dianne
