openjpa-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Alexey Romanov <alexey.v.roma...@gmail.com>
Subject Re: Change of MappingDefaults breaks OPENJPA_SEQUENCE_TABLE
Date Wed, 13 Jun 2012 08:00:44 GMT
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.

Mime
View raw message