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.
|