Мне нужно сопоставить имена верблюжьих имен с именами, выделенными яркими символами, в моем текущем проекте, который использует EclipseLink из-за исторических причин. Я знаю, что мы можем индивидуально настраивать сопоставление имен в JPA, но у нас есть длинный список имен верблюжьих дел, которые нужно изменить, поэтому мы хотим избежать такого рода кодов шаблонов, если это возможно.Настроить сопоставление имени поля JPA с помощью EclipseLink
Я хочу достичь следующего. Предположим, у нас есть класс сущностей, как показано ниже:
@Entity
public class FooBar {
@Id @GeneratedValue
private Long id;
@Temporal(TemporalType.TIMESTAMP)
private Date dateCreated;
}
Я хочу, чтобы этот класс карты в таблицу с именем «foo_bar» и столбцы «Идентификация» и «date_created». Обратите внимание, что все имена в базе данных находятся в нижнем регистре.
Я googled вокруг и нашел решение для изменения имен таблиц. Однако я не могу понять, как изменить имена полей в классе сущностей.
Ниже приведена моя настройка сопоставления имен, где метод updateFieldNameMappings()
не отображает fieldName
до field_name
, чего я хочу достичь. Проблема сводится к тому, как получить имя поля, как в определении класса. Итак, как мне это сделать в EclipseLink?
public class JpaNameMappingCustomizer implements SessionCustomizer {
@Override
public void customize(Session session) throws Exception {
Map<Class, ClassDescriptor> descs = session.getDescriptors();
Collection<ClassDescriptor> descriptors = descs.values();
// This code assumes single table per descriptor!
for (ClassDescriptor desc : descriptors) {
updateTableNameMapping(desc);
updateFieldNameMapping(desc);
}
}
private void updateTableNameMapping (ClassDescriptor desc) {
Class clazz = desc.getJavaClass();
String tableName = camelCaseToUnderscore(clazz.getSimpleName());
desc.setTableName(tableName);
}
private void updateFieldNameMapping (ClassDescriptor desc) {
// build name maps
Field[] fields = desc.getJavaClass().getDeclaredFields();
String tableName = desc.getTableName();
Map<String,String> nameMap = new HashMap<>();
String prefix = tableName + ".";
for(Field field : fields) {
String name = field.getName();
String key = prefix + name.toUpperCase();
String value = prefix + camelCaseToUnderscore(name);
nameMap.put(key, value);
}
for (DatabaseMapping mapping : desc.getMappings()) {
if (mapping.isDirectToFieldMapping()) {
DirectToFieldMapping directMapping = (DirectToFieldMapping) mapping;
String oldFieldName = directMapping.getFieldName(); // format: table_name.FIELD
directMapping.setFieldName(nameMap.get(oldFieldName));
}
}
}
private String camelCaseToUnderscore(String camelCase) {
return camelCase.trim().replaceAll("(?<!^)[A-Z](?!$)", "_$0").toLowerCase();
}
}
редактировать 11/10/13 Я сделал некоторые хакерство и изменил настройщик. updateFieldNameMapping()
все еще не делает этого трюка. Мне кажется, что это утверждение directMapping.setFieldName(nameMap.get(oldFieldName))
внутри метода фактически не изменяет сопоставление имени поля, что меня действительно смущает.
редактировать 11/11/13 Я забыл, чтобы понять, что я имел eclipselink.session.customizer
включен в persistence.xml
. А именно, у меня есть строка, как показано ниже в persistence.xml
:
<property name="eclipselink.session.customizer" value="pkg.JpaNameMappingCustomizer"/>
Когда ты скажите, что это не дает то, что вы хотите, что именно вы имеете в виду? – JamesB
@JamesB: Спасибо за вопрос. Я обновил свой пост. Надеюсь, теперь это ясно. – JBT
setFieldName должен создать объект DatabaseField из переданной строки, поэтому проверьте, что getFieldName возвращает то, что вы ожидаете после вызова. Вы можете видеть, когда вызывается вызов? Поскольку он работает только с прямыми сопоставлениями полей (базовые отображения JPA), любые другие поля, определенные в других отображениях, будут исключены. – Chris