I need to map camel-case names to underscore-separated names in my current project, which uses EclipseLink, due to historical reasons. I know we can customize name mapping i
In case you want to distinguish between non-annotated elements and annotated elements using @Column annotations, then I found a very beautiful example doing this:
public class CamelCaseSessionCustomizer implements SessionCustomizer {
@Override
public void customize(Session session) throws SQLException {
for (ClassDescriptor descriptor : session.getDescriptors().values()) {
// Only change the table name for non-embedable entities with no
// @Table already
if (!descriptor.getTables().isEmpty() && descriptor.getAlias().equalsIgnoreCase(descriptor.getTableName())) {
String tableName = addUnderscores(descriptor.getTableName());
descriptor.setTableName(tableName);
for (IndexDefinition index : descriptor.getTables().get(0).getIndexes()) {
index.setTargetTable(tableName);
}
}
for (DatabaseMapping mapping : descriptor.getMappings()) {
// Only change the column name for non-embedable entities with
// no @Column already
if (mapping instanceof AggregateObjectMapping) {
for (Association association : ((AggregateObjectMapping) mapping).getAggregateToSourceFieldAssociations()) {
DatabaseField field = (DatabaseField) association.getValue();
field.setName(addUnderscores(field.getName()));
for (DatabaseMapping attrMapping : session.getDescriptor(((AggregateObjectMapping) mapping).getReferenceClass()).getMappings()) {
if (attrMapping.getAttributeName().equalsIgnoreCase((String) association.getKey())) {
((AggregateObjectMapping) mapping).addFieldTranslation(field, addUnderscores(attrMapping.getAttributeName()));
((AggregateObjectMapping) mapping).getAggregateToSourceFields().remove(association.getKey());
break;
}
}
}
} else if (mapping instanceof ObjectReferenceMapping) {
for (DatabaseField foreignKey : ((ObjectReferenceMapping) mapping).getForeignKeyFields()) {
foreignKey.setName(addUnderscores(foreignKey.getName()));
}
} else if (mapping instanceof DirectMapMapping) {
for (DatabaseField referenceKey : ((DirectMapMapping) mapping).getReferenceKeyFields()) {
referenceKey.setName(addUnderscores(referenceKey.getName()));
}
for (DatabaseField sourceKey : ((DirectMapMapping) mapping).getSourceKeyFields()) {
sourceKey.setName(addUnderscores(sourceKey.getName()));
}
} else {
DatabaseField field = mapping.getField();
if (field != null && !mapping.getAttributeName().isEmpty() && field.getName().equalsIgnoreCase(mapping.getAttributeName())) {
field.setName(addUnderscores(mapping.getAttributeName()));
}
}
}
}
}
private static String addUnderscores(String name) {
if (name.equalsIgnoreCase("begintime")) {
System.err.println();
}
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();
}
}
From https://gist.github.com/ganeshs/c0deb77ffae33dee4555
Perhaps you could use my session customizer. It converts table names, and field names to Camel case. It supports inheritance and embeded entities. I tested for 2 years, and I got no issues or side effects. Enjoy it!
import java.sql.SQLException;
import java.util.Locale;
import java.util.Vector;
import org.eclipse.persistence.config.SessionCustomizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.tools.schemaframework.IndexDefinition;
public class CamelNamingStrategy implements SessionCustomizer {
public static String unqualify(final String qualifiedName) {
int loc = qualifiedName.lastIndexOf(".");
return loc < 0 ? qualifiedName : qualifiedName.substring(qualifiedName.lastIndexOf(".") + 1);
}
@Override
public void customize(final Session session) throws SQLException {
for (ClassDescriptor descriptor : session.getDescriptors().values()) {
if (!descriptor.getTables().isEmpty()) {
// Take table name from @Table if exists
String tableName = null;
if (descriptor.getAlias().equalsIgnoreCase(descriptor.getTableName())) {
tableName = unqualify(descriptor.getJavaClassName());
} else {
tableName = descriptor.getTableName();
}
tableName = camelCaseToUnderscore(tableName);
descriptor.setTableName(tableName);
for (IndexDefinition index : descriptor.getTables().get(0).getIndexes()) {
index.setTargetTable(tableName);
}
Vector<DatabaseMapping> mappings = descriptor.getMappings();
camelCaseToUnderscore(mappings);
} else if (descriptor.isAggregateDescriptor() || descriptor.isChildDescriptor()) {
camelCaseToUnderscore(descriptor.getMappings());
}
}
}
private void camelCaseToUnderscore(Vector<DatabaseMapping> mappings) {
for (DatabaseMapping mapping : mappings) {
DatabaseField field = mapping.getField();
if (mapping.isDirectToFieldMapping() && !mapping.isPrimaryKeyMapping()) {
String attributeName = mapping.getAttributeName();
String underScoredFieldName = camelCaseToUnderscore(attributeName);
field.setName(underScoredFieldName);
}
}
}
private String camelCaseToUnderscore(final 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(Locale.ENGLISH);
}
}
Instead of
directMapping.setFieldName(nameMap.get(oldFieldName ));
try:
directMapping.getField().resetQualifiedName(nameMap.get(oldFieldName));
This does the trick for me under EclipseLink 2.5.0
I think you have missed adding following line in your persistence.xml
to say EclipseLink
to use your own SessionCustomizer
<property name="eclipselink.session.customizer" value="your.company.package.name.JpaNameMappingCustomizer"/>
Refer
http://www.eclipse.org/eclipselink/documentation/2.5/dbws/creating_dbws_services002.htm
http://eclipse.org/eclipselink/documentation/2.4/jpa/extensions/p_session_customizer.htm#CHDFBIEI