OpenJPA — Расширение значений по умолчанию Persistencemapping для преобразования верблюжьего регистра в символы подчеркивания

#jpa #openjpa

#jpa #openjpa

Вопрос:

 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)) amp;amp; Character.isUpperCase(buf.charAt(i)) amp;amp; Character.isLowerCase(buf.charAt(i   1))) {
                buf.insert(i  , '_');
            }
        }
        return buf.toString().toLowerCase();
    }
}
  

Приведенный выше код корректно генерирует DDL в Openjpa 1.2.2 путем преобразования имен полей верблюжьего регистра в символы подчеркивания в базе данных. Однако операции сохранения, такие как em.persist(), генерируют ошибочный SQL и завершаются сбоем.

 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]
  

Обратите внимание, что openjpa добавляет «5» к каждому столбцу. Не уверен, откуда это берется. Сгенерированный DDL для FOO_FILE является:

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

Просто чтобы дважды проверить, не ошиблась ли моя логика, я заменил correctName() методом суперкласса (который использует венгерскую нотацию).

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

Это тоже не удается.

Кто-нибудь успешно расширил PersistenceMappingDefaults для изменения имен столбцов / таблиц? Кажется, openjpa слишком сложен по сравнению с Hibernate в этом отношении.

Ответ №1:

Я протестировал ваш код выше, и он работает для OpenJPA 2.2.0.

Успешно преобразовал имена полей верблюжьего регистра в символы подчеркивания в базе данных.

Таким образом, поле private String taxRate; ссылается на столбец БД TAX_RATE без необходимости комментировать @Column(name = 'TAX_RATE')

Помните, что persistence.xml необходимо, чтобы подобное свойство было определено в <persistence-unit> :

     <properties>
        <property name="openjpa.jdbc.MappingDefaults"
            value="com.myproject.ImprovedMappingDefaults"/>
    </properties>
  

Было бы здорово, если бы команда OpenJPA могла использовать это в качестве опции, например, Removehungarianannotation

Ответ №2:

Это работает в текущих версиях OpenJPA. Смотрите пример здесь.