Search code examples
jpaopenjpa

OpenJPA - Extending PersistenceMappingDefaults to convert Camel-Case to Underscores


public class ImprovedMappingDefaults extends PersistenceMappingDefaults {
    @Override
    protected void correctName(Table table, Column col) {
        String name = col.getName();
        name = addUnderscores(name);
        col.setName(dict.getValidColumnName(name, table));
    }

    // taken from Hibernate's ImprovedNamingStrategy
    private static String addUnderscores(String name) {
        StringBuffer buf = new StringBuffer(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();
    }
}

The above code generates DDL correctly in Openjpa 1.2.2 by converting camel case field names to underscores in the db. However persistence operations like em.persist() generate erroneous SQL and fails.

org.apache.openjpa.lib.jdbc.ReportingSQLException: Column not found: VERSION5 in statement [INSERT INTO FOO_FILE (file_id, VERSION5, DATETIME05, FILE_NAME5, INPUT_SYSTEM5, IS_END_OF_DAY5, SEQUENCE_NUMBER5, TOTAL_AMOUNT5, TOTAL_COUNT5, MY_FILE_ID5) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)] {INSERT INTO FOO_FILE (file_id, VERSION5, DATETIME05, FILE_NAME5, INPUT_SYSTEM5, IS_END_OF_DAY5, SEQUENCE_NUMBER5, TOTAL_AMOUNT5, TOTAL_COUNT5, MY_FILE_ID5) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)} [code=-28, state=S0022]

Note that openjpa is appending "5" to each column. Not sure where this is coming from. The DDL for FOO_FILE generated is:

CREATE TABLE FOO_FILE (file_id BIGINT NOT NULL, VERSION INTEGER, DATETIME0 TIME, FILE_NAME VARCHAR(100), INPUT_SYSTEM VARCHAR(3), IS_END_OF_DAY BIT, SEQUENCE_NUMBER BIGINT, TOTAL_AMOUNT NUMERIC, TOTAL_COUNT INTEGER, MY_FILE_ID VARCHAR(255), PRIMARY KEY (file_id))

Just to double check if my logic was wrong, I replaced correctName() with the super class method (that uses Hungarian notation).

protected void correctName(Table table, Column col) {
    String name = col.getName();
    name = removeHungarianNotation(name);
    col.setName(dict.getValidColumnName(name, table));
}

That fails too.

Has anyone successfully extended PersistenceMappingDefaults to change column/table names? It seems openjpa is too complicated compared to Hibernate in this regard.


Solution

  • It works in current versions of OpenJPA. See example here.